【问题标题】:With R, iterate over data frames, perform math operations on each one, append results in new data frame使用 R,迭代数据帧,对每个数据帧执行数学运算,将结果附加到新数据帧中
【发布时间】:2017-06-26 16:48:06
【问题描述】:

我在 R 中有一个巨大的数据框 (A),如下所示:

Letters   Frequency   Numbers
a         0.15        1
b         0.67        2
c         0.85        7
d         0.4         3

我想先根据“频率”列的取值范围(4个大小为0.25的频率箱)将A分成4个数据框,从0到1,这样我得到:

A1 [0, 0.25]

Letters   Frequency   Numbers
a         0.15        1

A2 [0.25, 0.5]

Letters   Frequency   Numbers
d         0.4         3

A3 [0.5, 0.75]

Letters   Frequency   Numbers
b         0.67        2

A4 [0.75, 1]

Letters   Frequency   Numbers
c         0.85        7

以迭代方式并按照频率区间的顺序,我想在 A1、A2、A3 和 A4 中执行数学运算(例如,op1 = Numbers - 2;op2 = Numbers * 10)并创建一个数据带有附加结果的框架 B:

B

bin            op1    op2   
[0, 0.25]      -1     10 
[0.25, 0.5]     1     30 
[0.5, 0.75]     0     20 
[0.75, 1]       5     70

我想我不需要创建 A1、A2、A3 和 A4(理想情况下我只想与 A 一起工作),并且有一种更优雅的方法可以通过直接遍历频率箱来获得 B,但是我在这个例子中创建它们是为了清楚地解释原理。我认为这可以通过 lapply 完成,但我不确定如何。非常感谢您。

【问题讨论】:

    标签: r loops dataframe lapply


    【解决方案1】:

    具有拆分-应用-组合方法的基本 R 方法是

    do.call(rbind, lapply(split(dd, findInterval(dd$Frequency, c(0, .25, .5, .75, 1))),
                          function(i) within(i, { # create variables, remove Numbers
                                             op1 <- Numbers - 2
                                             op2 <- Numbers * 10
                                             Numbers <- NULL})))
    

    返回

      Letters Frequency op2 op1
    1       a      0.15  10  -1
    2       d      0.40  30   1
    3       b      0.67  20   0
    4       c      0.85  70   5
    

    这里,findInterval 根据频率对观察结果进行分箱,split 根据这些分箱拆分 data.frame 并相应地对数据进行排序,lapplywithin 用于为每个组构造新变量.

    【讨论】:

    • 非常感谢@Imo。很高兴收到您对我发布的最后一条评论的反馈。
    • 如果您在 mr-flick 的回答中提及您的评论,我无法将其可视化。从我的第二次阅读来看,它似乎足以作为一个新问题发布,并附有一个很好的例子来说明这个问题。
    【解决方案2】:

    您可以在 dplyr 中使用简单的 group_by 来完成此操作。以您的数据为例。

    dd<-read.table(text="Letters   Frequency   Numbers
    a         0.15        1
    b         0.67        2
    c         0.85        7
    d         0.4         3", header=T)
    

    你可以运行

    library(dplyr)
    
    dd %>% 
        group_by(bin=cut(Frequency, breaks=seq(0,1,by=.25))) %>% 
        transmute(op1=Numbers-2, op2=Numbers*10) %>% 
        arrange(bin)
    

    我们使用cut() 创建分箱组,然后使用transmute() 创建新列(同时删除旧列)。

    【讨论】:

    • 谢谢@MrFlick,它也对你有用。如果我想对包含特定列(例如“字母”)中具有特定单词(例如“基因”)的所有行的子数据帧执行这些数学运算,请问您将如何迭代地(或使用 dplyr)执行此操作.问题是这些词出现在上下文中,例如“基因/内含子/错义”,因此我不能单独按“基因”对它们进行分组。我知道如何使用 grepl 提取这些子数据帧并手动进行操作,但我无法以优雅的方式进行操作。非常感谢。
    • 不清楚你的意思。您应该创建一个新帖子,其中包含可重现的示例,其中包含示例输入和所需的输出,就像您在此问题中所做的那样。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-10
    • 2015-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多