【问题标题】:Calculating percentage value (based on maximum value) for each element in df; however in specified columns计算df中每个元素的百分比值(基于最大值);但是在指定的列中
【发布时间】:2018-12-24 18:52:20
【问题描述】:

没有复杂的解释,让我们创建一个小的示例数据框:

A <- c(1,2,3,4)
B <- c(3,4,5,7)
C <- c(3,4,7,3)
D <- c(8,3,2,4)
df <- data.frame(A,B,C,D)

> df
  A B C D
1 1 3 3 8
2 2 4 4 3
3 3 5 7 2
4 4 7 3 4

我想使用apply 函数计算 A、B 和 C 列中的百分比值。基于每行最大值的百分比值,换句话说:

%_to_be_calculated <- df[i,j] * 100 / max(df[i,1:3])

其中j列索引A,BCi 表中的后续行。

期望的输出:

  A     B       C       D
1 33.33 100     100     8
2 50    100     100     3
3 42.85 71.42   100     2
4 57.14 100     42.85   4

我的解决方案

apply(df,1,function(i) lapply(i[1:3],function(j) j*100/max(i[1:3])))

它可以工作,但是它返回列表列表...我想要一个不错的 df,你能告诉我如何替换当前 df 中的值吗?

谢谢。

【问题讨论】:

    标签: r dataframe apply lapply


    【解决方案1】:

    使用数据表:

    df <- data.table(A,B,C,D)
    df[,
       c(
         lapply(.SD, function(x) x/do.call(pmax,.SD[,.(A,B,C)])*100),
         D=list(D)
         ),
       .SDcols=c('A','B','C')
       ]
    

    【讨论】:

    • 但这会产生不同的结果。
    【解决方案2】:

    虽然我确实喜欢 do.call()+pmax() 解决方案 --- 通常当您有明确定义的问题时,最简单的解决方案是将其包装在循环中,然后再考虑如何优化。

    df2 <- df
    for (i in 1:nrow(df)) {
      mi <- max(df[i, 1:3])
      for (j in 1:3) {
        df2[i, j] <- df[i, j] * 100 / mi
      }
    }
    df2
             A         B         C D
    1 33.33333 100.00000 100.00000 8
    2 50.00000 100.00000 100.00000 3
    3 42.85714  71.42857 100.00000 2
    4 57.14286 100.00000  42.85714 4
    

    这打破了问题,你可以看到内循环很容易矢量化:

    for (i in 1:nrow(df)) {
      mi <- max(df[i, 1:3]) 
      df2[i, 1:3] <- df[i, 1:3] * 100 / mi
    }
    

    现在你的问题是如何更有效地找到每一行的最大值turns out many people have thought about before

    【讨论】:

    • 对不起,如果这显得居高临下,我的意图也是通过分享原则来提供帮助。
    【解决方案3】:

    有多种方法可以做到这一点。

    普通apply方式:

    df[1:3] <- t(apply(df[1:3], 1, function(x) x/max(x) * 100))
    df
    
    #         A         B         C D
    #1 33.33333 100.00000 100.00000 8
    #2 50.00000 100.00000 100.00000 3
    #3 42.85714  71.42857 100.00000 2
    #4 57.14286 100.00000  42.85714 4
    

    这也可以通过:

    df[1:3] <- df[1:3] * 100/apply(df[1:3], 1, max)
    

    更快的方法是使用do.callpmax

    df[1:3] <- df[1:3] * 100 /do.call(pmax, df[1:3])
    

    【讨论】:

    • 还有df[-4] / matrixStats::rowMaxs(as.matrix(df[-4]))
    • 感谢您的帮助!在这种情况下,我必须仔细研究pmaxdo.call
    猜你喜欢
    • 2021-12-25
    • 2013-12-27
    • 2015-01-17
    • 1970-01-01
    • 1970-01-01
    • 2020-12-09
    • 2021-03-16
    • 2021-10-09
    • 1970-01-01
    相关资源
    最近更新 更多