【问题标题】:Averaging an increasing number of columns of a dataframe平均数据帧中越来越多的列
【发布时间】:2017-08-11 21:09:25
【问题描述】:

我有一个包含 7 列的数据框 (wc2):

    cm5      cm10      cm15      cm20      cm25      cm30       run_time
1 0.1221060 0.1221060 0.1221060 0.1221060 0.1221060 0.1221060        0
2 0.4084525 0.4028010 0.3617393 0.2595060 0.1294412 0.1220099        2
3 0.4087809 0.4042515 0.3711077 0.3119956 0.2241836 0.1290348        4
4 0.4088547 0.4045780 0.3732053 0.3218224 0.2611785 0.1720426        6
5 0.4088770 0.4046887 0.3739936 0.3255557 0.2739738 0.2081264        8
6 0.4088953 0.4047649 0.3744183 0.3273794 0.2798225 0.2273250       10

对于每一行(run_time),我想首先平均第一列,然后是第一列和第二列,然后是第一列、第二列和第三列,依此类推,直到第六列。平均结果应该在新列或新数据框中(我不介意)。 我使用以下代码做到了:

wc2$dia10 <- wc2$cm5
wc2$dia20 <- rowMeans(wc2[c("cm5", "cm10")])
wc2$dia30 <- rowMeans(wc2[c("cm5", "cm10", "cm15")])
wc2$dia40 <- rowMeans(wc2[c("cm5", "cm10", "cm15", "cm20")])
wc2$dia50 <- rowMeans(wc2[c("cm5", "cm10", "cm15", "cm20", "cm25")])
wc2$dia60 <- rowMeans(wc2[c("cm5", "cm10", "cm15", "cm20", "cm25", "cm30")])

根据我对 R 的基本知识,我发现有一种更好的方法可以做到这一点,但我不知道怎么做。特别是当我有更多的列时。 我查看了“汇总并增加 R 中数据框的列数”的答案,但无法理解或将其应用于我的数据。

感谢您的帮助

【问题讨论】:

    标签: r


    【解决方案1】:

    您可以使用Reduceaccumulate = TRUE 参数,如下所示,

    sapply(Reduce(c, 1:(ncol(df)-1), accumulate = TRUE)[-1], function(i) rowMeans(df[i]))
    

    或者要得到准确的输出,

    setNames(data.frame(df[1],sapply(Reduce(c, 1:(ncol(df)-1),accumulate = TRUE)[-1], function(i) 
               rowMeans(df[i]))), paste0('dia', seq(from = 10, to = ncol(df[-1])*10, by = 10)))
    

    或者正如@A5C1D2H2I1M1N2O1R2T1 在 cmets 中建议的那样,

    do.call(cbind, setNames(lapply(1:6, function(x) rowMeans(df[1:x])),
                                            paste0("dia", seq(10, 60, 10)))
    

    双方都给予,

        dia10     dia20     dia30     dia40     dia50     dia60
    1 0.1221060 0.1221060 0.1221060 0.1221060 0.1221060 0.1221060
    2 0.4084525 0.4056268 0.3909976 0.3581247 0.3123880 0.2806583
    3 0.4087809 0.4065162 0.3947134 0.3740339 0.3440639 0.3082257
    4 0.4088547 0.4067164 0.3955460 0.3771151 0.3539278 0.3236136
    5 0.4088770 0.4067829 0.3958531 0.3782787 0.3574178 0.3325359
    6 0.4088953 0.4068301 0.3960262 0.3788645 0.3590561 0.3371009
    

    或者将其添加到原始数据框中,然后,

    cbind(df, setNames(lapply(1:6, function(x) rowMeans(df[1:x])),
                                        paste0("dia", seq(10, 60, 10))))
    

    【讨论】:

    • 或者只是 setNames(lapply(1:6, function(x) rowMeans(mydf[1:x])),paste0("dia", seq(10, 60, 10)))cbind 与原始数据。
    • @A5C1D2H2I1M1N2O1R2T1 我看到 1...1, 2...1, 2, 3...我的大脑说积累,积累! :p
    • 这很好用!我不明白我怎么没有弄清楚。我想过 lapply 功能,但找不到使用它的方法。
    • 有人能解释一下为什么独立数据框需要“do.call”,而添加到原始数据框只需要“cbind”吗?
    • 好吧,do.call(来自文档)在第一种情况下用于构造和执行函数调用(请参阅here for more info)。第二种情况,我们直接调用cbind两个列表(数据框就是列表)
    【解决方案2】:

    这是applycumsum 的替代方法。使用rowMeans 几乎可以肯定是更可取的,但这种方法一次性完成计算。

    setNames(data.frame(t(apply(dat[1:6], 1, cumsum) / 1:6)),
             paste0("dia", seq(10, 60, 10)))
          dia10     dia20     dia30     dia40     dia50     dia60
    1 0.1221060 0.1221060 0.1221060 0.1221060 0.1221060 0.1221060
    2 0.4084525 0.4056268 0.3909976 0.3581247 0.3123880 0.2806583
    3 0.4087809 0.4065162 0.3947134 0.3740339 0.3440639 0.3082257
    4 0.4088547 0.4067164 0.3955460 0.3771151 0.3539278 0.3236136
    5 0.4088770 0.4067829 0.3958531 0.3782787 0.3574178 0.3325359
    6 0.4088953 0.4068301 0.3960262 0.3788645 0.3590561 0.3371009
    

    使用更智能的 Reduce("+" 和 @alexis-laz 建议的累积,我们可以做到

    mapply("/", Reduce("+", dat[1:6], accumulate = TRUE), 1:6)
    

    或获取具有所需名称的 data.frame

    setNames(data.frame(mapply("/", Reduce("+", dat[1:6], accumulate = TRUE), 1:6)),
             paste0("dia", seq(10, 60, 10)))
    

    下面更丑的代码遵循相同的想法,没有mapply

    setNames(data.frame(Reduce("+", dat[1:6], accumulate = TRUE)) /
                        rep(1:6, each=nrow(dat)), paste0("dia", seq(10, 60, 10)))
    

    【讨论】:

    • apply(, 1, cumsum) 的替代方法是使用 Reduce: mapply("/", Reduce("+", dat[1:6], accumulate = TRUE), 1:6)。我相信,一般来说,使用这种累积和方法应该更有效,因为它可以避免重新添加相同的列
    • 虽然我更喜欢使用较短的代码行,但它也能正常工作:S 让我更容易理解。
    • 谢谢,@alexis_laz。太棒了。我忘记了 Reduce("+", ... 的累积方法(即使它的近亲在 soto 的回答中)。
    • @alexis_laz 这是一个不错的建议。您应该在某处添加它(要么回答它,要么将它添加到我的答案或 lmo 的答案中)......Idk......无论如何......把它放在那里:)
    • @alexis_laz 我在上面添加了您的答案,并进行了修改以返回一个 data.frame,但是如果您想发布,我会删除它,并且肯定会为您的帖子投票。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-15
    • 1970-01-01
    • 2018-04-20
    相关资源
    最近更新 更多