【问题标题】:Multiply Columns of two different dataframes将两个不同数据框的列相乘
【发布时间】:2018-08-14 22:25:32
【问题描述】:

如何有效地将行数相同但列数不同的两个不同数据帧的列相乘。 我有两个数据集成交量和价格,我想将每个成交量列乘以每个价格列,这样生成的数据框将有 nXm 列(n 在第一个数据帧中是 ncols,m 在第二个数据帧中是 ncols )。

set.seed(159) # for reproducibility
volumes <- as.data.frame(cbind(Year = 2000:2004, 
                               matrix(round(runif(25, 50, 100), 0), 
                                      nrow = 5, ncol = 5)))
names(volumes) <- c("Year", paste(rep("V", 5), seq(1:5), sep = ""))
volumes
  Year V1 V2 V3 V4 V5
1 2000 56 52 88 81 52
2 2001 81 56 90 76 69
3 2002 81 92 69 93 69
4 2003 56 68 77 80 72
5 2004 51 58 62 53 62

set.seed(159)
prices <-   as.data.frame(cbind(Year = 2000:2004, 
                                matrix(round(runif(20, 5, 15), 0), 
                                       nrow = 5, ncol = 2)))
names(prices) <-  c("Year", paste(rep("P", 2), seq(1:2), sep = ""))
prices
  Year P1 P2
1 2000  6  5
2 2001 11  6
3 2002 11 13
4 2003  6  9
5 2004  5  7

【问题讨论】:

  • Year 的值是否总是相同的?也就是说,我们可以将一列乘以另一列,还是需要先将行匹配Year?
  • 对于我当前的问题,我有相同的问题,但最好知道如何匹配然后相乘,以防它们不一样。

标签: r


【解决方案1】:

这是一种可能的方法。这不是最有效的,但可以完成工作:

result <- c()
for(i in names(volumes)) {
  for(j in names(prices)) {
    result <- c(result, volumes[i] * prices[j])
  }
}

# outcome of every combination as you want (m * n columns)
result_df <- as.data.frame(result)

# resulting column names are a bit messy but you can rename easily
# names(result_df) <- # your list of m * n names

【讨论】:

  • 谢谢,这很接近,但需要修改以保持Years 完整并摆脱原始列
【解决方案2】:
prices <- structure(list(Year = c(2001, 2003, 2002, 2000, 2004), P1 = c(15, 
8, 13, 12, 7), P2 = c(7, 10, 8, 14, 10)), row.names = c(2L, 4L, 
3L, 1L, 5L), class = "data.frame")

volumes <- structure(list(Year = c(2000, 2001, 2002, 2003, 2004), V1 = c(76, 
78, 55, 74, 80), V2 = c(61, 80, 77, 68, 65), V3 = c(56, 52, 91, 
69, 90), V4 = c(50, 59, 51, 66, 58), V5 = c(75, 57, 57, 80, 59
)), class = "data.frame", row.names = c(NA, -5L))

我们可以分两步使用lapply 和purrr::reduce。

首先,我们使用lapply 循环遍历prices 的每一列,并乘以volumes。 lapply 返回一个列表,每个操作的输出作为一个列表项。

volumes_mult <- lapply(prices[,-1], function(p) {
    cbind(Year = volumes$Year, volumes[,-1] * p)
})

然后我们使用reduce 对列表中的每个项目应用*_join 操作。我建议使用purrr::reduce 而不是base R Reduce,因为它可以更轻松地为*_join 提供额外的参数(我们需要by= 参数才能正确加入表格)。您还可以自定义 suffix= 参数以选择如何重命名来自不同表的相同行:

purrr::reduce(volumes_mult, dplyr::full_join, by='Year', suffix = paste0('_', names(x)))

  Year V1_P1 V2_P1 V3_P1 V4_P1 V5_P1 V1_P2 V2_P2 V3_P2 V4_P2 V5_P2
1 2000  1140   915   840   750  1125   532   427   392   350   525
2 2001   624   640   416   472   456   780   800   520   590   570
3 2002   715  1001  1183   663   741   440   616   728   408   456
4 2003   888   816   828   792   960  1036   952   966   924  1120
5 2004   560   455   630   406   413   800   650   900   580   590

【讨论】:

  • @AshishSinghal 你最初的问题并不清楚,但我看到你现在已经澄清了。我已经更新了答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-28
  • 2020-04-06
  • 2021-09-15
  • 2018-01-24
  • 2017-08-27
  • 1970-01-01
  • 2015-11-05
相关资源
最近更新 更多