R 减去/找出具有不同列数的两个数据帧之间的差异

R 减去/找出具有不同列数的两个数据帧之间的差异,r,dataframe,dplyr,difference,subtraction,R,Dataframe,Dplyr,Difference,Subtraction,我对R比较陌生,还没有找到任何地方可以回答这个问题 我有两个数据帧,行数相同,列数不同。我想减去匹配列中的值,以确定两个数据帧之间的差异 例如,这两个数据帧与我正在使用的数据帧相似: df1<-data.frame(Measure=rep("test",3),Filename=c("filename1","filename2","filename3"),Op1=c(79,72,95),Op2=c(NA,NA,5),Op3=c(75,64,66),Op4=c(86,71,58)) F

我对R比较陌生,还没有找到任何地方可以回答这个问题

我有两个数据帧,行数相同,列数不同。我想减去匹配列中的值,以确定两个数据帧之间的差异

例如,这两个数据帧与我正在使用的数据帧相似:

df1<-data.frame(Measure=rep("test",3),Filename=c("filename1","filename2","filename3"),Op1=c(79,72,95),Op2=c(NA,NA,5),Op3=c(75,64,66),Op4=c(86,71,58))

   Filename  Op1  Op2  Op3  Op4
1  filename1  79   NA   75   86
2  filename2  72   NA   64   71
3  filename3  95   5    66   58

df2<-data.frame(Measure=rep("test",3),Filename=c("filename1","filename2","filename3"),Op1=c(9,NA,5),Op4=c(80,70,50))

   Filename  Op1  Op4
1  filename1   9   80
2  filename2   NA  70
3  filename3   5   50
我想要的是类似于执行计算df1-df2得到:

  Measure  Filename  Op1  Op2  Op3  Op4
1  test   filename1  70   NA   75   6
2  test   filename2  72   NA   64   1
3  test   filename3  90   5    66   8
我尝试用
diff
替换函数中的
sum
,但没有成功

你知道怎么做吗

编辑-我意识到该功能包括对列表的引用,我将这些数据帧保存在其中并对其进行了更改

跟进:处理NA值

到目前为止,答案是有效的,但在使用实际数据进行测试时,我注意到在df2有NA但df1有值的情况下,结果输出包含NA,而不是df1中的值。我将把df2中的一个值更改为NA以反映这一点

在@akrun和@IceCreamToucan当前的回答中,输出将是

  Measure  Filename  Op1  Op2  Op3  Op4
1  test   filename1  70   NA   75   6
2  test   filename2  NA   NA   64   1
3  test   filename3  90   5    66   8

我假设这是代码中的某个地方的NA.rm=T,或者我需要在过程的前面处理NA值,但是如果知道答案中是否有可以解决这一问题的调整,这将是非常有用的。

这里有一个使用
数据,table
进行连接的选项。获取两个数据集中通用的列名(
intersect
),并删除不需要比较的列名(
setdiff

使现代化 与NA相比的任何值都返回NA,类似地

72-NA
#[1] NA
为了避免此问题,我们可以用0替换
NA
,然后进行差异处理

setDT(df1)[df2, (nm1) := Map(function(x, y) replace(x, is.na(x), 0) - 
     replace(y, is.na(y), 0), 
    mget(nm1),mget(paste0("i.", nm1))), on = .(Measure, Filename)]

df1
#   Measure  Filename Op1 Op2 Op3 Op4
#1:    test filename1  70  NA  75   6
#2:    test filename2  72  NA  64   1
#3:    test filename3  90   5  66   8

这里有一个使用
数据,table
进行连接的选项。获取两个数据集中通用的列名(
intersect
),并删除不需要比较的列名(
setdiff

使现代化 与NA相比的任何值都返回NA,类似地

72-NA
#[1] NA
为了避免此问题,我们可以用0替换
NA
,然后进行差异处理

setDT(df1)[df2, (nm1) := Map(function(x, y) replace(x, is.na(x), 0) - 
     replace(y, is.na(y), 0), 
    mget(nm1),mget(paste0("i.", nm1))), on = .(Measure, Filename)]

df1
#   Measure  Filename Op1 Op2 Op3 Op4
#1:    test filename1  70  NA  75   6
#2:    test filename2  72  NA  64   1
#3:    test filename3  90   5  66   8

如果要将
df1
中的一行与
df2
中的同一行进行比较,即匹配索引并且不检查某些联接列的相等性,则可以从
df1[公共列]
中减去
df2[公共列]
,然后将结果分配回
df1
(或一份副本)


如果要将
df1
中的一行与
df2
中的同一行进行比较,即匹配索引并且不检查某些联接列的相等性,则可以从
df1[公共列]
中减去
df2[公共列]
,然后将结果分配回
df1
(或一份副本)


很好,谢谢。我也差不多能理解你的解释——我想!我可以在哪里找到更多关于这里发生的事情的信息?快速查询-我注意到这会用我想要的输出“覆盖”df1帧。作业在这里是如何进行的?我是否使用df3@MWilding我会使用
copy
df3@MWilding即
traceem(df1)#[1]“df3 traceem(df3)[1]”
抱歉,我刚刚更新了这个问题-当df2包含NA但df1有一个值时出现了问题感谢更新,我可以确认这是有效的。我想我可能会回到源数据,在那里处理NA值,以避免下游出现类似的问题。这很好,谢谢。我也差不多能理解你的解释——我想!我可以在哪里找到更多关于这里发生的事情的信息?快速查询-我注意到这会用我想要的输出“覆盖”df1帧。作业在这里是如何进行的?我是否使用df3@MWilding我会使用
copy
df3@MWilding即
traceem(df1)#[1]“df3 traceem(df3)[1]”
抱歉,我刚刚更新了这个问题-当df2包含NA但df1有一个值时出现了问题感谢更新,我可以确认这是有效的。我想我可能会回到源数据,在那里处理NA值,以避免下游出现类似的问题。如果我理解正确,您要做的是识别包含数据的公共列名,复制“主”数据帧,然后为已识别的公共列执行减法。我很喜欢这个:)是的,这是一个准确的描述。请你看看问题的更新,看看你是否愿意更新答案?如果我理解正确,你所做的是识别包含数据的常用列名,复制“主”数据帧,然后对标识的公共列执行减法。我很喜欢这个:)是的,这是一个准确的描述。请你看看问题的更新,看看你是否愿意更新答案?
72-NA
#[1] NA
setDT(df1)[df2, (nm1) := Map(function(x, y) replace(x, is.na(x), 0) - 
     replace(y, is.na(y), 0), 
    mget(nm1),mget(paste0("i.", nm1))), on = .(Measure, Filename)]

df1
#   Measure  Filename Op1 Op2 Op3 Op4
#1:    test filename1  70  NA  75   6
#2:    test filename2  72  NA  64   1
#3:    test filename3  90   5  66   8
common <- intersect(names(df1), names(df2))[-(1:2)]
new <- df1 # or copy(df1) if df1 is a data.table
new[common] <- df1[common] - df2[common]


new
#   Measure  Filename Op1 Op2 Op3 Op4
# 1    test filename1  70  NA  75   6
# 2    test filename2  70  NA  64   1
# 3    test filename3  90   5  66   8
common <- intersect(names(df1), names(df2))[-(1:2)]
new <- df1
new[common] <- new[common] - replace(df2[common], is.na(df2[common]), 0)


new
#   Measure  Filename Op1 Op2 Op3 Op4
# 1    test filename1  70  NA  75   6
# 2    test filename2  72  NA  64   1
# 3    test filename3  90   5  66   8