Julia DataFrames,在特定索引处插入新行

Julia DataFrames, Insert new row at specific index

有没有办法在特定索引处向现有数据框添加一行?

例如你有一个 3 行 1 列的数据框

df = DataFrame(x = [2,3,4])

X
2
3
4

以任何方式执行以下操作:

insert!(df, 1, [1])

为了得到

X
1
2
3
4

我知道我可能会连接两个数据帧 df = [df1; df2] 但我希望在我想插入一行时避免垃圾处理大型 DF。

在 DataFrames 0.21.4 中只写(我给出了两个选项:一个是广播,很短但创建了一个临时对象;另一个是 foreach 写的时间更长但分配的少了一点) :

julia> df = DataFrame(x = [1,2,3], y = ["a", "b", "c"])
3×2 DataFrame
│ Row │ x     │ y      │
│     │ Int64 │ String │
├─────┼───────┼────────┤
│ 1   │ 1     │ a      │
│ 2   │ 2     │ b      │
│ 3   │ 3     │ c      │

julia> insert!.(eachcol(df), 2, [4, "d"]) # creates an temporary object but is terse
2-element Array{Array{T,1} where T,1}:
 [1, 4, 2, 3]
 ["a", "d", "b", "c"]

julia> df
4×2 DataFrame
│ Row │ x     │ y      │
│     │ Int64 │ String │
├─────┼───────┼────────┤
│ 1   │ 1     │ a      │
│ 2   │ 4     │ d      │
│ 3   │ 2     │ b      │
│ 4   │ 3     │ c      │

julia> foreach((c, v) -> insert!(c, 2, v), eachcol(df), [4, "d"]) # does not create a temporary object

julia> df
5×2 DataFrame
│ Row │ x     │ y      │
│     │ Int64 │ String │
├─────┼───────┼────────┤
│ 1   │ 1     │ a      │
│ 2   │ 4     │ d      │
│ 3   │ 4     │ d      │
│ 4   │ 2     │ b      │
│ 5   │ 3     │ c      │

请注意,上述操作不是原子操作(如果您要添加的元素类型与列中允许的元素类型不匹配,它可能会损坏您的数据框)。

如果您想要提供自动升级的安全操作,请使用:

julia> df = DataFrame(x = [1,2,3], y = ["a", "b", "c"])
3×2 DataFrame
│ Row │ x     │ y      │
│     │ Int64 │ String │
├─────┼───────┼────────┤
│ 1   │ 1     │ a      │
│ 2   │ 2     │ b      │
│ 3   │ 3     │ c      │

julia> [view(df, 1:1, :); DataFrame(names(df) .=> ['a', 'b']); view(df, 3:3, :)]
3×2 DataFrame
│ Row │ x   │ y   │
│     │ Any │ Any │
├─────┼─────┼─────┤
│ 1   │ 1   │ a   │
│ 2   │ 'a' │ 'b' │
│ 3   │ 3   │ c   │

(虽然有点慢,但会创建一个新的数据框)

已弃用

原来的答案在这里。它对 1.0 版本之前的 Julia 有效(以及与之兼容的 DataFrames.jl 版本)。

我猜你想原地做。然后你可以像这样使用 insert! 函数:

julia> df = DataFrame(x = [1,2,3], y = ["a", "b", "c"])
3×2 DataFrames.DataFrame
│ Row │ x │ y │
├─────┼───┼───┤
│ 1   │ 1 │ a │
│ 2   │ 2 │ b │
│ 3   │ 3 │ c │

julia> foreach((v,n) -> insert!(df[n], 2, v), [4, "d"], names(df))

julia> df
4×2 DataFrames.DataFrame
│ Row │ x │ y │
├─────┼───┼───┤
│ 1   │ 1 │ a │
│ 2   │ 4 │ d │
│ 3   │ 2 │ b │
│ 4   │ 3 │ c │

当然,您必须确保添加的集合中的列数正确。

如果您接受使用 DataFrame 的未导出内部结构,您可以做得更简单:

julia> df = DataFrame(x = [1,2,3], y = ["a", "b", "c"])
3×2 DataFrames.DataFrame
│ Row │ x │ y │
├─────┼───┼───┤
│ 1   │ 1 │ a │
│ 2   │ 2 │ b │
│ 3   │ 3 │ c │

julia> insert!.(df.columns, 2, [4, "d"])
2-element Array{Array{T,1} where T,1}:
 [1, 4, 2, 3]
 String["a", "d", "b", "c"]

julia> df
4×2 DataFrames.DataFrame
│ Row │ x │ y │
├─────┼───┼───┤
│ 1   │ 1 │ a │
│ 2   │ 4 │ d │
│ 3   │ 2 │ b │
│ 4   │ 3 │ c │