这是这样做的方法:
5×12 DataFrame
│ Row │ grh │ anc │ anc1 │ anc2 │ anc3 │ anc4 │ anc5 │ anc6 │ anc7 │ anc8 │ anc9 │ anc10 │
│ │ Int64 │ Int64 │ Float64 │ Float64 │ Float64 │ Float64 │ Float64 │ Float64 │ Float64 │ Float64 │ Float64 │ Float64 │
├─────┼───────┼───────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ 1 │ 2 │ 5 │ 0.1 │ 0.12 │ 0.18 │ 0.14 │ 0.15 │ 0.19 │ 0.2 │ 0.1 │ 0.21 │ 0.24 │
│ 2 │ 3 │ 7 │ 0.03299 │ 0.05081 │ 0.0355 │ 0.02884 │ 0.03054 │ 0.0332 │ 0.03115 │ 0.02177 │ 0.04903 │ 0.04399 │
│ 3 │ 4 │ 3 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │
│ 4 │ 5 │ 4 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │
│ 5 │ 6 │ 1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │
julia> transform(df, [r"anc" => ByRow((x...) -> x[x[1]+i]) => "lap$i" for i in 1:3])
5×15 DataFrame
│ Row │ grh │ anc │ anc1 │ anc2 │ anc3 │ anc4 │ anc5 │ anc6 │ anc7 │ anc8 │ anc9 │ anc10 │ lap1 │ lap2 │ lap3 │
│ │ Int64 │ Int64 │ Float64 │ Float64 │ Float64 │ Float64 │ Float64 │ Float64 │ Float64 │ Float64 │ Float64 │ Float64 │ Float64 │ Float64 │ Float64 │
├─────┼───────┼───────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ 1 │ 2 │ 5 │ 0.1 │ 0.12 │ 0.18 │ 0.14 │ 0.15 │ 0.19 │ 0.2 │ 0.1 │ 0.21 │ 0.24 │ 0.15 │ 0.19 │ 0.2 │
│ 2 │ 3 │ 7 │ 0.03299 │ 0.05081 │ 0.0355 │ 0.02884 │ 0.03054 │ 0.0332 │ 0.03115 │ 0.02177 │ 0.04903 │ 0.04399 │ 0.03115 │ 0.02177 │ 0.04903 │
│ 3 │ 4 │ 3 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │
│ 4 │ 5 │ 4 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │
│ 5 │ 6 │ 1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │
(我保留宽输出不截断任何列)
在代码中,我假设您只想生成 :lap1、:lap2 和 :lap3 列,这意味着应该允许 anc 最多取值 8(如果它是 9 或更多你会在代码中得到一个错误,因为没有源可以从中获取数据)。
理解其工作原理的关键是解析:
[r"anc" => ByRow((x...) -> x[x[1]+i]) => "lap$i" for i in 1:3]
理解意味着我们将为i创建三个变量,范围从1到3。所以让我们解决例如i=1。现在:
-
r"anc" 意味着我们会将所有名称中包含"anc" 的列按照它们在数据框中的出现顺序传递给我们的函数(因此首先是"anc",然后是后缀从1 到@987654335 的列@)。这些值将作为位置参数传递
- 然后
ByRow((x...) -> x[x[1]+i]) 表示我们定义了一个函数,它将逐行传递数据,(x...) -> 部分表示x 将是一个包含传递的位置参数的元组,因为我们知道"anc" 是拳头我们将其称为x[1] 的列,然后将i 添加到其中以获得我们感兴趣的列;
- 最后
"lap$i" 为我们提供了输出变量的名称
另一种写法是:
julia> transform(df, [AsTable(r"anc") => ByRow(x -> x[Symbol("anc", x.anc+i-1)]) => "lap$i" for i in 1:3])
5×15 DataFrame
│ Row │ grh │ anc │ anc1 │ anc2 │ anc3 │ anc4 │ anc5 │ anc6 │ anc7 │ anc8 │ anc9 │ anc10 │ lap1 │ lap2 │ lap3 │
│ │ Int64 │ Int64 │ Float64 │ Float64 │ Float64 │ Float64 │ Float64 │ Float64 │ Float64 │ Float64 │ Float64 │ Float64 │ Float64 │ Float64 │ Float64 │
├─────┼───────┼───────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ 1 │ 2 │ 5 │ 0.1 │ 0.12 │ 0.18 │ 0.14 │ 0.15 │ 0.19 │ 0.2 │ 0.1 │ 0.21 │ 0.24 │ 0.15 │ 0.19 │ 0.2 │
│ 2 │ 3 │ 7 │ 0.03299 │ 0.05081 │ 0.0355 │ 0.02884 │ 0.03054 │ 0.0332 │ 0.03115 │ 0.02177 │ 0.04903 │ 0.04399 │ 0.03115 │ 0.02177 │ 0.04903 │
│ 3 │ 4 │ 3 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │
│ 4 │ 5 │ 4 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │ 0.0 │
│ 5 │ 6 │ 1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │ 0.1 │
不同之处在于AsTable 使x 成为NamedTuple,因此我们可以使用作为x.anc 或Symbols 传递的列名来索引x,如x[Symbol("anc", x.anc+i-1)]。
编辑
如果您想以牺牲代码复杂性为代价获得更快的速度,您可以编写:
m = Matrix(df[!, 3:end])
v = df.anc
insertcols!(df, ["lap$k" => getindex.(Ref(m), axes(df, 1), v .+ k .- 1) for k in 1:3]...)