DataFrames中leftjoin!()替换列值的关键字参数或解决方案
在DataFrames中使用leftjoin!实现列值替换而非报错
原代码报错的核心原因是:x和y存在连接键外的同名列d,leftjoin!默认不允许这种情况,因为无法自动处理列冲突。要实现用y的d列值替换x中匹配行的d值,同时保留不匹配行的原d值,可以通过以下两种方式实现:
方法一:重命名列后合并替换(原地修改x)
using DataFrames x = DataFrame(a=[1,2,3],b=[4,5,6],c=[7,20,9],d=[nothing,99,nothing]) y = DataFrame(a=[1,2,3],b=[4,5,6],c=[7,8,9],d=[10,11,12]) # 重命名y的d列,避免连接时的列名冲突 leftjoin!(x, rename(y, :d => :d_y), on=[:a, :b, :c]) # 优先使用y的d值,无匹配时保留x原d值 x.d = coalesce.(x.d_y, x.d) # 删除临时生成的d_y列 select!(x, Not(:d_y))
方法二:先连接再处理,最后覆盖原x
using DataFrames x = DataFrame(a=[1,2,3],b=[4,5,6],c=[7,20,9],d=[nothing,99,nothing]) y = DataFrame(a=[1,2,3],b=[4,5,6],c=[7,8,9],d=[10,11,12]) # 执行左连接,允许重复列(自动生成d_1列) result = leftjoin(x, y, on=[:a, :b, :c], makeunique=true) # 合并d和d_1列,优先取y的d值 result.d = coalesce.(result.d_1, result.d) # 删除临时列 select!(result, Not(:d_1)) # 将结果覆盖原x x .= result
运行任意一种方法后,x都会变为期望的输出:
3×4 DataFrame Row │ a b c d │ Int64 Int64 Int64 Int64? ─────┼────────────────────────────── 1 │ 1 4 7 10 2 │ 2 5 20 99 3 │ 3 6 9 12
关键逻辑说明
rename(y, :d => :d_y)或makeunique=true都是为了规避列名冲突,让左连接操作能正常执行。coalesce.(a, b)函数会逐个元素检查:如果a不为nothing则取a的值,否则取b的值,正好匹配我们"匹配行用y的d值,不匹配行留x原d值"的需求。
内容的提问来源于stack exchange,提问作者wanderinganon
相关产品推荐
相关产品推荐

