【问题标题】:How to subtract one record from another data frame in R如何从R中的另一个数据框中减去一条记录
【发布时间】:2019-01-10 06:42:44
【问题描述】:

我有两个数据框。一个数据框只有 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))

【问题讨论】:

  • 签出?data.table::fsetdiff

标签: r


【解决方案1】:

试试这个..

# 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

【讨论】:

    【解决方案2】:

    如果你直接做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]
    【解决方案3】:

    我们可以使用

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-19
      • 2014-06-10
      • 2013-12-04
      • 2020-09-28
      • 2018-08-29
      • 2016-09-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多