如何在R中从一个数据框中减去另一个记录

3
我有两个数据框。一个数据框只有1条记录和3列。另一个数据框有6行和3列。 现在我想从数据框2的值中减去数据框1的值。
示例数据:
df1 = structure(list(col1 = 2L, col2 = 3L, col3 = 4L), .Names = c("col1", 
"col2", "col3"), class = "data.frame", row.names = c(NA, -1L))

df2 = structure(list(col1 = c(1L, 2L, 4L, 5L, 6L, 3L), col2 = c(1L, 
2L, 4L, 3L, 5L, 7L), col3 = c(6L, 4L, 3L, 6L, 4L, 6L)), .Names = c("col1", "col2", "col3"), class = "data.frame", row.names = c(NA, -6L))

最终输出应该如下所示:

output = structure(list(col1 = c(-1L, 0L, 2L, 3L, 4L, 1L), col2 = c(-2L, 
-1L, 1L, 0L, 2L, 4L), col3 = c(2L, 0L, -1L, 2L, 0L, 2L)), .Names =      c("col1","col2", "col3"), class = "data.frame", row.names = c(NA, -6L))

1
请查看?data.table::fsetdiff - chinsoon12
3个回答

4

试试这个...

# Creating Datasets
df1 = structure(list(col1 = 2L, col2 = 3L, col3 = 4L), .Names = c("col1", "col2", "col3"), class = "data.frame", row.names = c(NA, -1L))
df2 = structure(list(col1 = c(1L, 2L, 4L, 5L, 6L, 3L), col2 = c(1L,2L, 4L, 3L, 5L, 7L), col3 = c(6L, 4L, 3L, 6L, 4L, 6L)), .Names = c("col1", "col2", "col3"), class = "data.frame", row.names = c(NA, -6L))

# Output
data.frame(sapply(names(df1), function(i){df2[[i]] - df1[[i]]}))
#    col1 col2 col3
# 1   -1   -2    2
# 2    0   -1    0
# 3    2    1   -1
# 4    3    0    2
# 5    4    2    0
# 6    1    4    2

3
如果您直接执行 df2 - df1,则会得到:
df2 - df1

在 Ops.data.frame(df2, df1) 中出现错误: ‘-’ 仅适用于大小相等的数据框

因此,让我们通过重复行使 df1df2 大小相同,然后再进行减法操作。

df2 - df1[rep(seq_len(nrow(df1)), nrow(df2)), ]

#  col1 col2 col3
#1   -1   -2    2
#2    0   -1    0
#3    2    1   -1
#4    3    0    2
#5    4    2    0
#6    1    4    2

或者另一种选项是使用没有复制行的mapply
mapply("-", df2, df1)

如果您想要返回一个数据框而不是矩阵,可以使用以下代码:
data.frame(mapply("-", df2, df1))

#  col1 col2 col3
#1   -1   -2    2
#2    0   -1    0
#3    2    1   -1
#4    3    0    2
#5    4    2    0
#6    1    4    2

在Python中,我可以使用以下代码来实现。df2-df1.values[0] - RSK

2
我们可以使用 "sweep":
x <- sweep(df2, 2, unlist(df1), "-")

#test if same as output
identical(output, x)
# [1] TRUE

注意,它的速度比 mapply 慢两倍:

df2big <- data.frame(col1 = runif(100000),
                     col2 = runif(100000),
                     col3 = runif(100000))

microbenchmark::microbenchmark(
  mapply = data.frame(mapply("-", df2big, df1)),
  sapply = data.frame(sapply(names(df1), function(i){df2big[[i]] - df1[[i]]})),
  sweep = sweep(df2big, 2, unlist(df1), "-"))
# Unit: milliseconds
#   expr       min        lq     mean    median        uq      max neval
# mapply  5.239638  7.645213 11.49182  8.514876  9.345765 60.60949   100
# sapply  5.250756  5.518455 10.94827  8.706027 10.091841 59.09909   100
# sweep  10.572785 13.912167 21.18537 14.985525 16.737820 64.90064   100

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接