【问题标题】:R multiply 2 dataframes based on factor labelR基于因子标签乘以2个数据帧
【发布时间】:2014-02-13 21:16:53
【问题描述】:

我有 2 个数据框。第一个有多行,第二个有单行。我需要将第一帧的每一行乘以第二帧的单行。第一个数据帧名为Costs,如下所示:

Pounds, Zone.A, Zone.B, Zone.C, Zone.D, Zone.E
5,      10.0,   20.0,   1.00,   23.0,   34.5
10,     20.0,   40.0,   10.0,   34.5,   54.0
15,     40.0,   100.0,  100.0,  67.8,   98.2

第二个表名为Weights,如下所示:

Zone.A, Zone.B, Zone.C
0.5,    0.3,    0.2

当我将它们相乘时,如果Weights 表中缺少一个因子,我需要将Costs 表中的相应因子变为0.0。我想要的结果是:

Pounds, Zone.A, Zone.B, Zone.C, Zone.D, Zone.E
5,      5.0,    6.00,   0.20,   0.0,    0.0
10,     10.0,   12.0,   2.00,   0.0,    0.0
15,     20.0,   30.0,   20.0,   0.0,    0.0

之后,我将按行对 Zone.* 列求和,以获得我已经知道该怎么做的总数,但如果我可以跳过中间步骤,那就太好了。我正在寻找的最终结果是:

Pounds, Total
5,      11.2
10,     24.0
15,     70.0

我不确定如何使用尺寸不匹配的数据框执行此操作,因此非常感谢任何帮助。

【问题讨论】:

    标签: r dataframe apply mapply


    【解决方案1】:
    Costs <- read.table(text = "Pounds, Zone.A, Zone.B, Zone.C, Zone.D, Zone.E
    5,      10.0,   20.0,   1.00,   23.0,   34.5
    10,     20.0,   40.0,   10.0,   34.5,   54.0
    15,     40.0,   100.0,  100.0,  67.8,   98.2", header = TRUE, sep = ",")
    
    Weights <- read.table(text = "Zone.A, Zone.B, Zone.C
    0.5,    0.3,    0.2", header = TRUE, sep = ",")
    
    CostsMat <- as.matrix(Costs[names(Weights)])
    
    total <- CostsMat %*% matrix(unlist(Weights), ncol = 1)
    
    data.frame(Pounds = Costs$Pounds, Total = total)
    
    ##   Pounds Total
    ## 1      5  11.2
    ## 2     10  24.0
    ## 3     15  70.0
    

    【讨论】:

    • 这并没有严格按照 OP 的要求做,尽管我猜结果是一样的,而且这样更容易(+1)。
    • @BrodieG true.. 虽然我看不出有任何理由为什么你想要/需要将零添加到权重中,如果你只是要将它们相加的话。也为您 +1 完全遵循 OP :)
    【解决方案2】:

    这是一个选项:

    missing.names <- names(Costs[-1])[!names(Costs[-1]) %in% names(Weights)]
    Weights[, missing.names] <- do.call(data.frame, as.list(rep(0, length(missing.names))))
    cbind(
      Pounds=Costs$Pounds, 
      Total=rowSums(t(t(as.matrix(Costs[2:ncol(Costs)])) * unlist(Weights2[names(Costs[-1])])))
    )
    #      Pounds Total
    # [1,]      5  11.2
    # [2,]     10  24.0
    # [3,]     15  70.0
    

    【讨论】:

    • 感谢您的回复。我确定我也需要这种中间状态,但对于这种情况,我最终只需要对列求和。不过谢谢!
    【解决方案3】:

    还有一种可能:

    library(reshape2)
    d1 <- melt(Costs, id.var = "Pounds")
    d2 <- melt(Weights)
    
    d1 <- merge(d1, d2, by = "variable", all.x = TRUE)
    d1$Total <- with(d1, value.x * value.y) 
    
    aggregate(Total ~ Pounds, data = d1, sum, na.rm = TRUE)
    
    #   Pounds Total
    # 1      5  11.2
    # 2     10  24.0
    # 3     15  70.0
    

    【讨论】:

      猜你喜欢
      • 2018-07-21
      • 1970-01-01
      • 2018-07-08
      • 2018-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-18
      • 1970-01-01
      相关资源
      最近更新 更多