在GroupedDataFrame上使用combine Julia函数,同时使用正则表达式引用列

在GroupedDataFrame上使用combine Julia函数,同时使用正则表达式引用列,julia,Julia,从这个问题可以看出,对于Julia来说,我是一个非常新的用户,只是尝试做一些我在python中已经做过的事情,在黑暗中有点磕磕绊绊。我现在正试图做的是基于特定的数据分组在多个列上创建一些简单的统计数据。所以在做了一些类似的事情之后: df = DataFrame(CSV.File(file)); gdf = groupby(df, :Class); combine(gdf, :V1 => maximum => :v1_max, :V1 => minimum => :v1

从这个问题可以看出,对于Julia来说,我是一个非常新的用户,只是尝试做一些我在python中已经做过的事情,在黑暗中有点磕磕绊绊。我现在正试图做的是基于特定的数据分组在多个列上创建一些简单的统计数据。所以在做了一些类似的事情之后:

df = DataFrame(CSV.File(file));
gdf = groupby(df, :Class);
combine(gdf, :V1 => maximum => :v1_max, :V1 => minimum => :v1_min, nrow)
其中df看起来像:

df[1:3, [:Class, :V1, :V2, :V10]]

     Class  V1        V2           V10
     Int64  Float64   Float64      Float64
1    0      -1.35981  -0.0727812   0.0907942
2    1      1.19186   0.266151     -0.166974
3    0      -1.35835  -1.34016     0.207643

我知道我可以做一些事情,比如:

df = DataFrame(CSV.File(file));
gdf = groupby(df, :Class);
combine(gdf, :V1 => maximum => :v1_max, :V1 => minimum => :v1_min, nrow)
但后来我发现我可以使用regex引用多个列,所以我的想法是做一些简单的事情,比如:

combine(gdf, r"V[0-9]{1,2}" => maximum)
并让Julia在一行中为与分组数据帧的正则表达式匹配的所有列生成最大值

我终于能够做到这一点,我猜这不是一个很好的有效的方式,因此,寻找任何人的帮助,以帮助我提高我的朱莉娅使用

foo = DataFrame(Class=[0, 1])
for v in ["V$i" for i in 1:28]
    foo = join(foo, 
               combine(gdf, v => maximum => string(v, "_max")), 
               combine(gdf, v => minimum => string(v, "_min")), 
               on=:Class)
end
只要写下:

combine(gdf, names(gdf, r"V[0-9]{1,2}") .=> maximum)
(注意
=>
前面的

在这种情况下,将自动生成目标列名

我上面写的是以下内容的简写:

combine(gdf, [n => maximum for n in names(gdf, r"V[0-9]{1,2}")])
另一种书写方式是:

combine(AsTable(r"V[0-9]{1,2}") => x -> map(maximum, x), gdf)
当保留旧列名时

combine
语法非常灵活。我建议您查看它的docstring以获得所有可用选项


考虑以下示例:

julia> using DataFrames

julia> passthrough(x...) = (@show x; x)
passthrough (generic function with 1 method)

julia> df = DataFrame(Class=[1,1,2], V1=1:3, V2=11:13)
3×3 DataFrame
│ Row │ Class │ V1    │ V2    │
│     │ Int64 │ Int64 │ Int64 │
├─────┼───────┼───────┼───────┤
│ 1   │ 1     │ 1     │ 11    │
│ 2   │ 1     │ 2     │ 12    │
│ 3   │ 2     │ 3     │ 13    │

julia> gdf = groupby(df, :Class)
GroupedDataFrame with 2 groups based on key: Class
First Group (2 rows): Class = 1
│ Row │ Class │ V1    │ V2    │
│     │ Int64 │ Int64 │ Int64 │
├─────┼───────┼───────┼───────┤
│ 1   │ 1     │ 1     │ 11    │
│ 2   │ 1     │ 2     │ 12    │
⋮
Last Group (1 row): Class = 2
│ Row │ Class │ V1    │ V2    │
│     │ Int64 │ Int64 │ Int64 │
├─────┼───────┼───────┼───────┤
│ 1   │ 2     │ 3     │ 13    │

julia> combine(gdf, r"V[0-9]{1,2}" .=> passthrough)
x = ([1, 2], [11, 12])
x = ([3], [13])
2×2 DataFrame
│ Row │ Class │ V1_V2_passthrough  │
│     │ Int64 │ Tuple…             │
├─────┼───────┼────────────────────┤
│ 1   │ 1     │ ([1, 2], [11, 12]) │
│ 2   │ 2     │ ([3], [13])        │

julia> combine(gdf, r"V[0-9]{1,2}" => passthrough)
x = ([1, 2], [11, 12])
x = ([3], [13])
2×2 DataFrame
│ Row │ Class │ V1_V2_passthrough  │
│     │ Int64 │ Tuple…             │
├─────┼───────┼────────────────────┤
│ 1   │ 1     │ ([1, 2], [11, 12]) │
│ 2   │ 2     │ ([3], [13])        │

julia> combine(gdf, names(gdf, r"V[0-9]{1,2}") .=> passthrough)
x = ([1, 2],)
x = ([3],)
x = ([11, 12],)
x = ([13],)
2×3 DataFrame
│ Row │ Class │ V1_passthrough │ V2_passthrough │
│     │ Int64 │ Tuple…         │ Tuple…         │
├─────┼───────┼────────────────┼────────────────┤
│ 1   │ 1     │ ([1, 2],)      │ ([11, 12],)    │
│ 2   │ 2     │ ([3],)         │ ([13],)        │

julia> combine(gdf, names(gdf, r"V[0-9]{1,2}") => passthrough)
x = ([1, 2], [11, 12])
x = ([3], [13])
2×2 DataFrame
│ Row │ Class │ V1_V2_passthrough  │
│     │ Int64 │ Tuple…             │
├─────┼───────┼────────────────────┤
│ 1   │ 1     │ ([1, 2], [11, 12]) │
│ 2   │ 2     │ ([3], [13])        │
尤其重要的是,了解传递给
组合的内容:

julia> r"V[0-9]{1,2}" .=> passthrough
r"V[0-9]{1,2}" => passthrough

julia> r"V[0-9]{1,2}" => passthrough
r"V[0-9]{1,2}" => passthrough

julia> names(gdf, r"V[0-9]{1,2}") .=> passthrough
2-element Array{Pair{String,typeof(passthrough)},1}:
 "V1" => passthrough
 "V2" => passthrough

julia> names(gdf, r"V[0-9]{1,2}") => passthrough
["V1", "V2"] => passthrough
如您所见,这一切都取决于传递给
combine
的内容。特别是
r“V[0-9]{1,2}.”=>passthrough
r“V[0-9]{1,2}=>passthrough
被解析为完全相同的表达式,在这种情况下,每个获得多个位置参数的组只调用一次
passthrough


另一方面,
names(gdf,r“V[0-9]{1,2}”)=>passthrough
make
passthrough
分别为每个组的每个列调用。

第一个代码块工作起来很有魅力。我不完全明白为什么广播名称的结果(…)确实有效,而不是如果我这样做:combine(gdf,r“V[0-9]{1,2}”。=>maximum)我在回答中扩展了解释。我希望它现在更清晰。非常感谢你花额外的时间和精力来帮助我和其他人获得更多的见解,而不仅仅是一个简单的答案!我可以看出,我还有很长的路要走,即使是在朱莉娅的中等熟练!