将 "any" 或 "all" 函数逐行应用于 Julia DataFrames.jl 中任意数量的布尔列
Apply "any" or "all" function row-wise to arbitrary number of Boolean columns in Julia DataFrames.jl
假设我有一个数据框,其中包含代表特定条件的多个布尔列:
df = DataFrame(
id = ["A", "B", "C", "D"],
cond1 = [true, false, false, false],
cond2 = [false, false, false, false],
cond3 = [true, false, true, false]
)
id
cond1
cond2
cond3
1
A
1
0
1
2
B
0
0
0
3
C
0
0
1
4
D
0
0
0
现在假设我想识别满足这些条件中的任何一个的行,即“A”和“C”。明确地做到这一点很容易:
df[:, :all] = df.cond1 .| df.cond2 .| df.cond3
但是当存在任意数量的条件时如何做到这一点,例如:
df[:, :all] = any.([ df[:, Symbol("cond$i")] for i in 1:3 ])
上面的 DimensionMismatch("tried to assign 3 elements to 4 destinations")
失败了,因为 any
函数是按列应用的,而不是按行应用的。所以真正的问题是:如何将 any
按行应用于数据框中的多个布尔列?
理想的输出应该是:
id
cond1
cond2
cond3
all
1
A
1
0
1
1
2
B
0
0
0
0
3
C
0
0
1
1
4
D
0
0
0
0
这是一种方法:
julia> df = DataFrame(
id = ["A", "B", "C", "D", "E"],
cond1 = [true, false, false, false, true],
cond2 = [false, false, false, false, true],
cond3 = [true, false, true, false, true]
)
5×4 DataFrame
Row │ id cond1 cond2 cond3
│ String Bool Bool Bool
─────┼─────────────────────────────
1 │ A true false true
2 │ B false false false
3 │ C false false true
4 │ D false false false
5 │ E true true true
julia> transform(df, AsTable(r"cond") .=> ByRow.([maximum, minimum]) .=> [:any, :all])
5×6 DataFrame
Row │ id cond1 cond2 cond3 any all
│ String Bool Bool Bool Bool Bool
─────┼───────────────────────────────────────────
1 │ A true false true true false
2 │ B false false false false false
3 │ C false false true true false
4 │ D false false false false false
5 │ E true true true true true
请注意,即使对于非常宽的表格,它也非常快:
julia> df = DataFrame(rand(Bool, 10_000, 10_000), :auto);
julia> @time transform(df, AsTable(r"x") .=> ByRow.([maximum, minimum]) .=> [:any, :all]);
0.059275 seconds (135.41 k allocations: 103.038 MiB)
在示例中我使用了正则表达式列选择器,当然您可以使用任何您喜欢的行选择器。
假设我有一个数据框,其中包含代表特定条件的多个布尔列:
df = DataFrame(
id = ["A", "B", "C", "D"],
cond1 = [true, false, false, false],
cond2 = [false, false, false, false],
cond3 = [true, false, true, false]
)
id | cond1 | cond2 | cond3 | |
---|---|---|---|---|
1 | A | 1 | 0 | 1 |
2 | B | 0 | 0 | 0 |
3 | C | 0 | 0 | 1 |
4 | D | 0 | 0 | 0 |
现在假设我想识别满足这些条件中的任何一个的行,即“A”和“C”。明确地做到这一点很容易:
df[:, :all] = df.cond1 .| df.cond2 .| df.cond3
但是当存在任意数量的条件时如何做到这一点,例如:
df[:, :all] = any.([ df[:, Symbol("cond$i")] for i in 1:3 ])
上面的 DimensionMismatch("tried to assign 3 elements to 4 destinations")
失败了,因为 any
函数是按列应用的,而不是按行应用的。所以真正的问题是:如何将 any
按行应用于数据框中的多个布尔列?
理想的输出应该是:
id | cond1 | cond2 | cond3 | all | |
---|---|---|---|---|---|
1 | A | 1 | 0 | 1 | 1 |
2 | B | 0 | 0 | 0 | 0 |
3 | C | 0 | 0 | 1 | 1 |
4 | D | 0 | 0 | 0 | 0 |
这是一种方法:
julia> df = DataFrame(
id = ["A", "B", "C", "D", "E"],
cond1 = [true, false, false, false, true],
cond2 = [false, false, false, false, true],
cond3 = [true, false, true, false, true]
)
5×4 DataFrame
Row │ id cond1 cond2 cond3
│ String Bool Bool Bool
─────┼─────────────────────────────
1 │ A true false true
2 │ B false false false
3 │ C false false true
4 │ D false false false
5 │ E true true true
julia> transform(df, AsTable(r"cond") .=> ByRow.([maximum, minimum]) .=> [:any, :all])
5×6 DataFrame
Row │ id cond1 cond2 cond3 any all
│ String Bool Bool Bool Bool Bool
─────┼───────────────────────────────────────────
1 │ A true false true true false
2 │ B false false false false false
3 │ C false false true true false
4 │ D false false false false false
5 │ E true true true true true
请注意,即使对于非常宽的表格,它也非常快:
julia> df = DataFrame(rand(Bool, 10_000, 10_000), :auto);
julia> @time transform(df, AsTable(r"x") .=> ByRow.([maximum, minimum]) .=> [:any, :all]);
0.059275 seconds (135.41 k allocations: 103.038 MiB)
在示例中我使用了正则表达式列选择器,当然您可以使用任何您喜欢的行选择器。