使用DataFrames与DataFramesMeta条件添加列时求值异常问题
问题分析与解决方案
你的问题出在逻辑运算符的使用上:在Julia中,||是标量短路逻辑或,它只能作用于单个布尔值,而你需要的是对每行的列元素进行逐行(元素级)的逻辑或判断,这时候应该用元素级的运算符.||。
修正后的代码
第一种方法(直接修正运算符):
using DataFrames, DataFramesMeta, StatsBase df = DataFrame(a = 1:10, b = StatsBase.sample([0, 1], 10, replace = true), c = StatsBase.sample([0, 1], 10, replace = true), d = StatsBase.sample([0, 1], 10, replace = true)) # 使用元素级逻辑或 .|| 替代标量 || @linq df |> transform(e = ifelse.(:b == 1 .|| :c == 1 .|| :d == 1, 1, 0))
第二种更简洁的写法(利用any逐行判断):
@linq df |> transform(e = Int.(any.(eachrow(select(df, [:b, :c, :d])) .== 1)))
为什么原代码失效?
原代码中的:b == 1会生成一个布尔向量(每行对应一个true/false),但||会尝试把整个向量当作单个布尔值来处理:
- Julia中,布尔向量转换为单个布尔值时,只有当**所有元素都是
true**时才返回true,否则返回false。 - 这就导致你的条件最终变成了一个单一的
false(除非b/c/d列全为1),ifelse.会把这个值广播到所有行,所以e列要么全0要么全1,完全不符合你的逐行判断需求。
示例运行结果
假设生成的df如下:
10×4 DataFrame Row │ a b c d │ Int64 Int64 Int64 Int64 ─────┼──────────────────────────── 1 │ 1 1 0 0 2 │ 2 0 1 0 3 │ 3 0 0 0 4 │ 4 1 1 1 5 │ 5 0 0 1 6 │ 6 0 1 1 7 │ 7 0 0 0 8 │ 8 1 0 1 9 │ 9 0 0 0 10 │ 10 1 1 0
修正后e列的结果会是:
Row │ e │ Int64 ─────┼─────── 1 │ 1 2 │ 1 3 │ 0 4 │ 1 5 │ 1 6 │ 1 7 │ 0 8 │ 1 9 │ 0 10 │ 1
完全符合“只要b/c/d有一个为1,e就为1”的需求。
内容的提问来源于stack exchange,提问作者buzaku
相关产品推荐
相关产品推荐

