Skip to content

Commit b618a44

Browse files
insert kdocs
1 parent 7951e04 commit b618a44

File tree

3 files changed

+279
-5
lines changed

3 files changed

+279
-5
lines changed

core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/insert.kt

Lines changed: 272 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,53 +10,231 @@ import org.jetbrains.kotlinx.dataframe.annotations.Interpretable
1010
import org.jetbrains.kotlinx.dataframe.annotations.Refine
1111
import org.jetbrains.kotlinx.dataframe.columns.ColumnAccessor
1212
import org.jetbrains.kotlinx.dataframe.columns.ColumnPath
13+
import org.jetbrains.kotlinx.dataframe.documentation.DocumentationUrls
14+
import org.jetbrains.kotlinx.dataframe.documentation.DslGrammarLink
15+
import org.jetbrains.kotlinx.dataframe.documentation.ExcludeFromSources
16+
import org.jetbrains.kotlinx.dataframe.documentation.Indent
17+
import org.jetbrains.kotlinx.dataframe.documentation.LineBreak
18+
import org.jetbrains.kotlinx.dataframe.documentation.SelectingColumns
1319
import org.jetbrains.kotlinx.dataframe.impl.api.insertImpl
1420
import org.jetbrains.kotlinx.dataframe.impl.columnName
1521
import org.jetbrains.kotlinx.dataframe.impl.removeAt
1622
import org.jetbrains.kotlinx.dataframe.util.DEPRECATED_ACCESS_API
23+
import org.jetbrains.kotlinx.dataframe.util.INSERT_AFTER_COL_PATH
24+
import org.jetbrains.kotlinx.dataframe.util.INSERT_AFTER_COL_PATH_REPLACE
1725
import kotlin.reflect.KProperty
1826

1927
// region DataFrame
2028

2129
// region insert
2230

31+
/**
32+
* This function does not immediately insert the new column but instead specify a column to insert and
33+
* returns an [InsertClause],
34+
* which serves as an intermediate step.
35+
* The [InsertClause] object provides methods to insert a new column using:
36+
* - [under][InsertClause.under] - inserts a new column under the specified column group.
37+
* - [after][InsertClause.after] - inserts a new column after the specified column.
38+
* - [at][InsertClause.at]- inserts a new column at the specified position.
39+
*
40+
* Each method returns a new [DataFrame] with the inserted column.
41+
*
42+
* Check out [Grammar].
43+
*
44+
* @include [SelectingColumns.ColumnGroupsAndNestedColumnsMention]
45+
*
46+
* See [Selecting Columns][InsertSelectingOptions].
47+
*
48+
* For more information: {@include [DocumentationUrls.Insert]}
49+
*
50+
* See also:
51+
* - [move][DataFrame.move] - move columns to a new position within the [DataFrame].
52+
* - [add][DataFrame.add] - add new columns to the [DataFrame]
53+
* (without specifying a position, to the end of the [DataFrame]).
54+
*/
55+
internal interface InsertDocs {
56+
57+
/**
58+
* {@comment Version of [SelectingColumns] with correctly filled in examples}
59+
* @include [SelectingColumns] {@include [SetInsertOperationArg]}
60+
*/
61+
interface InsertSelectingOptions
62+
63+
64+
/**
65+
* ## Insert Operation Grammar
66+
* {@include [LineBreak]}
67+
* {@include [DslGrammarLink]}
68+
* {@include [LineBreak]}
69+
*
70+
* **[`insert`][insert]**`(column: `[`DataColumn`][DataColumn]`)`
71+
*
72+
* {@include [Indent]}
73+
* `| `[`insert`][insert]`(name: `[`String`][String]`, infer: `[`Infer`][Infer]`, rowExpression: `[`RowExpression`][RowExpression]` }`
74+
*
75+
* {@include [Indent]}
76+
* __`.`__[**`under`**][InsertClause.under]` { `**`column: `[`ColumnSelector`][ColumnSelector]**` }`
77+
*
78+
* {@include [Indent]}
79+
* `| `__`.`__[**`under`**][InsertClause.under]`(columnPath: `[`ColumnPath`][ColumnPath]`)`
80+
*
81+
* {@include [Indent]}
82+
* `| `__`.`__[**`after`**][InsertClause.after]` { `**`column: `[`ColumnSelector`][ColumnSelector]**` }`
83+
*
84+
* {@include [Indent]}
85+
* `| `__`.`__[**`at`**][InsertClause.at]`(position: `[`Int`][Int]`)`
86+
*/
87+
interface Grammar
88+
}
89+
90+
/** {@set [SelectingColumns.OPERATION] [insert][insert]} */
91+
@ExcludeFromSources
92+
private interface SetInsertOperationArg
93+
94+
/**
95+
* Inserts the given [column] into this [DataFrame].
96+
*
97+
* {@include [InsertDocs]}
98+
*
99+
* ### Examples:
100+
* ```kotlin
101+
* // Insert a new column "age" under the column group with path ("info", "personal").
102+
* df.insert(age).under(pathOf("info", "personal"))
103+
*
104+
* // Insert a new column "count" after the column "url".
105+
* df.insert(count).after { url }
106+
* ```
107+
*
108+
* @param column A single [DataColumn] to insert into the [DataFrame].
109+
* @return An [InsertClause] for specifying the placement of the new column.
110+
*/
23111
public fun <T, C> DataFrame<T>.insert(column: DataColumn<C>): InsertClause<T> = InsertClause(this, column)
24112

113+
/**
114+
* Creates a new column using the provided [expression][AddExpression] and inserts it into this [DataFrame].
115+
*
116+
* {@include [AddExpressionDocs]}
117+
*
118+
* {@include [InsertDocs]}
119+
*
120+
* ## Examples
121+
*
122+
* ```kotlin
123+
* // Insert a new column "sum" that contains the sum of values from the "firstValue"
124+
* // and "secondValue" columns for each row after the "firstValue" column.
125+
* val dfWithSum = df.insert("sum") { firstValue + secondValue }.after { firstValue }
126+
*
127+
* // Insert a new "fibonacci" column with the Fibonacci sequence under a "math" column group:
128+
* // for the first two rows, the value is 1;
129+
* // for subsequent rows, it's the sum of the two previous Fibonacci values.
130+
* val dfWithFibonacci = df.insert("fibonacci") {
131+
* if (index() < 2) 1
132+
* else prev()!!.newValue<Int>() + prev()!!.prev()!!.newValue<Int>()
133+
* }.under("math")
134+
* ```
135+
*
136+
* @param name The name of the new column to be created and inserted.
137+
* @param infer Controls how values are inferred when building the new column. Defaults to [Infer.Nulls].
138+
* @param expression An [AddExpression] that computes the value for each row of the new column.
139+
* @return An [InsertClause] for specifying the placement of the newly created column.
140+
*/
25141
@Interpretable("Insert1")
26142
public inline fun <T, reified R> DataFrame<T>.insert(
27143
name: String,
28144
infer: Infer = Infer.Nulls,
29-
noinline expression: RowExpression<T, R>,
145+
noinline expression: AddExpression<T, R>,
30146
): InsertClause<T> = insert(mapToColumn(name, infer, expression))
31147

32148
@Deprecated(DEPRECATED_ACCESS_API)
33149
@AccessApiOverload
34150
public inline fun <T, reified R> DataFrame<T>.insert(
35151
column: ColumnAccessor<R>,
36152
infer: Infer = Infer.Nulls,
37-
noinline expression: RowExpression<T, R>,
153+
noinline expression: AddExpression<T, R>,
38154
): InsertClause<T> = insert(column.name(), infer, expression)
39155

40156
@Deprecated(DEPRECATED_ACCESS_API)
41157
@AccessApiOverload
42158
public inline fun <T, reified R> DataFrame<T>.insert(
43159
column: KProperty<R>,
44160
infer: Infer = Infer.Nulls,
45-
noinline expression: RowExpression<T, R>,
161+
noinline expression: AddExpression<T, R>,
46162
): InsertClause<T> = insert(column.columnName, infer, expression)
47163

48164
// endregion
49165

166+
/**
167+
* An intermediate class used in the [insert] operation.
168+
*
169+
* This class itself does not perform any insertions — it is a transitional step
170+
* before specifying how to insert the selected columns.
171+
* It must be followed by one of the inserting methods
172+
* to produce a new [DataFrame] with an inserted column.
173+
*
174+
* Use the following methods to perform the insertion:
175+
* - [under][InsertClause.under] - inserts a new column under the specified column group.
176+
* - [after][InsertClause.after] - inserts a new column after the specified column.
177+
* - [at][InsertClause.at]- inserts a new column at the specified position.
178+
*
179+
* See [Grammar][InsertDocs.Grammar] for more details.
180+
*/
50181
public class InsertClause<T>(internal val df: DataFrame<T>, internal val column: AnyCol) {
51182
override fun toString(): String = "InsertClause(df=$df, column=$column)"
52183
}
53184

54185
// region under
55186

187+
/**
188+
* Inserts the new column previously specified with [insert] under
189+
* the selected [column group][column].
190+
*
191+
* Works only with existing column groups.
192+
* To insert into a new column group, use the overloads:
193+
* `under(path: ColumnPath)` or `under(column: String)`.
194+
*
195+
* For more information: {@include [DocumentationUrls.Insert]}
196+
*
197+
* See [Grammar][InsertDocs.Grammar] for more details.
198+
*
199+
* See [SelectingColumns.Dsl].
200+
*
201+
* ### Examples
202+
* ```kotlin
203+
* // Insert a new column "age" under the column group with path ("info", "personal")
204+
* df.insert(age).under { info.personal }
205+
*
206+
* // Insert a new column "sum" under the only top-level column group
207+
* val dfWithSum = df.insert("sum") { a + b }.under { colGroups().single() }
208+
* ```
209+
*
210+
* @param column The [ColumnSelector] used to choose an existing column group in this [DataFrame]
211+
* under which the new column will be inserted.
212+
* @return A new [DataFrame] with the inserted column placed under the selected group.
213+
*/
56214
@Refine
57215
@Interpretable("Under0")
58216
public fun <T> InsertClause<T>.under(column: ColumnSelector<T, *>): DataFrame<T> = under(df.getColumnPath(column))
59217

218+
/**
219+
* Inserts the new column previously specified with [insert] under
220+
* the column group defined by the given [columnPath].
221+
*
222+
* {@include [org.jetbrains.kotlinx.dataframe.documentation.ColumnPathCreation]}
223+
*
224+
* See [Grammar][InsertDocs.Grammar] for more details.
225+
*
226+
* For more information: {@include [DocumentationUrls.Insert]}
227+
*
228+
* ### Example
229+
* ```kotlin
230+
* // Insert a new column "age" under the column group with path ("info", "personal")
231+
* df.insert(age).under(pathOf("info", "personal"))
232+
* ```
233+
*
234+
* @param columnPath The [ColumnPath] specifying the path to a column group in this [DataFrame]
235+
* under which the new column will be inserted.
236+
* @return A new [DataFrame] with the inserted column placed under the specified column group.
237+
*/
60238
@Refine
61239
@Interpretable("Under1")
62240
public fun <T> InsertClause<T>.under(columnPath: ColumnPath): DataFrame<T> =
@@ -70,6 +248,26 @@ public fun <T> InsertClause<T>.under(column: ColumnAccessor<*>): DataFrame<T> =
70248
@AccessApiOverload
71249
public fun <T> InsertClause<T>.under(column: KProperty<*>): DataFrame<T> = under(column.columnName)
72250

251+
/**
252+
* Inserts the new column previously specified with [insert] under
253+
* the given column group by its [name][column].
254+
*
255+
* If the column group with the provided [name][column] does not exist, it will be created automatically.
256+
*
257+
* For more information: {@include [DocumentationUrls.Insert]}
258+
*
259+
* See [Grammar][InsertDocs.Grammar] for more details.
260+
*
261+
* ### Example
262+
* ```kotlin
263+
* // Insert a new column "age" under the "info" column group.
264+
* df.insert(age).under("info")
265+
* ```
266+
*
267+
* @param column The [name][String] of the column group in this [DataFrame].
268+
* If the group does not exist, it will be created.
269+
* @return A new [DataFrame] with the inserted column placed under the specified column group.
270+
*/
73271
@Refine
74272
@Interpretable("Under4")
75273
public fun <T> InsertClause<T>.under(column: String): DataFrame<T> = under(pathOf(column))
@@ -78,29 +276,98 @@ public fun <T> InsertClause<T>.under(column: String): DataFrame<T> = under(pathO
78276

79277
// region after
80278

279+
/**
280+
* Inserts the new column previously specified with [insert]
281+
* at the position immediately after the selected [column] (on the same level).
282+
*
283+
* For more information: {@include [DocumentationUrls.Insert]}
284+
*
285+
* See [Grammar][InsertDocs.Grammar] for more details.
286+
*
287+
* See also: [SelectingColumns.Dsl].
288+
*
289+
* ### Examples:
290+
* ```kotlin
291+
* // Insert a new column "age" after the "name" column
292+
* df.insert(age).after { name }
293+
*
294+
* // Insert a new column "sum" after the nested "min" column (inside the "stats" column group)
295+
* val dfWithSum = df.insert("sum") { a + b }.after { stats.min }
296+
* ```
297+
*
298+
* @param column The [ColumnSelector] used to choose an existing column in this [DataFrame],
299+
* after which the new column will be inserted.
300+
* @return A new [DataFrame] with the inserted column placed after the selected column.
301+
*/
81302
@Refine
82303
@Interpretable("InsertAfter0")
83-
public fun <T> InsertClause<T>.after(column: ColumnSelector<T, *>): DataFrame<T> = after(df.getColumnPath(column))
304+
public fun <T> InsertClause<T>.after(column: ColumnSelector<T, *>): DataFrame<T> = afterImpl(df.getColumnPath(column))
84305

306+
/**
307+
* Inserts the new column previously specified with [insert]
308+
* at the position immediately after the column with the given [name][column].
309+
*
310+
* For more information: {@include [DocumentationUrls.Insert]}
311+
*
312+
* See [Grammar][InsertDocs.Grammar] for more details.
313+
*
314+
* See also: [SelectingColumns.ColumnNames].
315+
*
316+
* ### Example
317+
* ```kotlin
318+
* // Insert a new column "age" after the "name" column
319+
* df.insert(age).after("name")
320+
* ```
321+
*
322+
* @param column The [String] name of the column in this [DataFrame]
323+
* after which the new column will be inserted.
324+
* @return A new [DataFrame] with the inserted column placed after the specified column.
325+
*/
85326
public fun <T> InsertClause<T>.after(column: String): DataFrame<T> = df.add(this.column).move(this.column).after(column)
86327

87328
@Deprecated(DEPRECATED_ACCESS_API)
88329
@AccessApiOverload
89-
public fun <T> InsertClause<T>.after(column: ColumnAccessor<*>): DataFrame<T> = after(column.path())
330+
public fun <T> InsertClause<T>.after(column: ColumnAccessor<*>): DataFrame<T> = afterImpl(column.path())
90331

91332
@Deprecated(DEPRECATED_ACCESS_API)
92333
@AccessApiOverload
93334
public fun <T> InsertClause<T>.after(column: KProperty<*>): DataFrame<T> = after(column.columnName)
94335

336+
@Deprecated(INSERT_AFTER_COL_PATH, ReplaceWith(INSERT_AFTER_COL_PATH_REPLACE), DeprecationLevel.ERROR)
95337
public fun <T> InsertClause<T>.after(columnPath: ColumnPath): DataFrame<T> {
96338
val dstPath = ColumnPath(columnPath.removeAt(columnPath.size - 1) + column.name())
97339
return df.insertImpl(dstPath, column).move { dstPath }.after { columnPath }
98340
}
99341

342+
internal fun <T> InsertClause<T>.afterImpl(columnPath: ColumnPath): DataFrame<T> {
343+
val dstPath = ColumnPath(columnPath.removeAt(columnPath.size - 1) + column.name())
344+
return df.insertImpl(dstPath, column).move { dstPath }.after { columnPath }
345+
}
346+
100347
// endregion
101348

102349
// region at
103350

351+
/**
352+
* Inserts the new column previously specified with [insert]
353+
* at the given [position] in the [DataFrame].
354+
*
355+
* The new column will be placed at the specified index, shifting existing columns to the right.
356+
*
357+
* For more information: {@include [DocumentationUrls.Insert]}
358+
*
359+
* See [Grammar][InsertDocs.Grammar] for more details.
360+
*
361+
* ### Example
362+
* ```kotlin
363+
* // Insert a new column "age" at index 3
364+
* df.insert(age).at(3)
365+
* ```
366+
*
367+
* @param position The [Int] index where the new column should be inserted.
368+
* Columns currently at this index and after will be shifted right.
369+
* @return A new [DataFrame] with the inserted column placed at the specified position.
370+
*/
104371
@Refine
105372
@Interpretable("InsertAt")
106373
public fun <T> InsertClause<T>.at(position: Int): DataFrame<T> = df.add(column).move(column).to(position)

core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/DocumentationUrls.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,4 +134,7 @@ internal interface DocumentationUrls {
134134

135135
/** [See `format` on the documentation website.]({@include [Url]}/format.html) */
136136
interface Format
137+
138+
/** [See `insert` on the documentation website.]({@include [Url]}/insert.html) */
139+
interface Insert
137140
}

core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/util/deprecationMessages.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ internal const val COL_TYPE_INSTANT =
137137
"kotlinx.datetime.Instant is deprecated in favor of kotlin.time.Instant. Either migrate to kotlin.time.Instant and use ColType.StdlibInstant or use ColType.DeprecatedInstant. $MESSAGE_1_0 and migrated to kotlin.time.Instant in 1.1."
138138
internal const val COL_TYPE_INSTANT_REPLACE = "ColType.DeprecatedInstant"
139139

140+
internal const val INSERT_AFTER_COL_PATH = "This `after()` overload will be removed in favor of `after { }` with Column Selection" +
141+
"DSL. $MESSAGE_1_0"
142+
internal const val INSERT_AFTER_COL_PATH_REPLACE = "this.after { colPath }"
143+
140144
// endregion
141145

142146
// region WARNING in 1.0, ERROR in 1.1

0 commit comments

Comments
 (0)