按照类别范围对数据框进行分类或切分,并使用ddply进行汇总。

3

我有一个关于ddply和subset的问题。

我的数据框df长这样:

df <- read.table(textConnection(
"   id v_idn v_seed v_time v_pop v_rank v_perco 
    1  15    125648 0      150   1      15      
    2  17    125648 0      120   2      5       
    3  18    125648 0      100   3      6       
    4  52    125648 0      25    4      1       

    5  17    125648 10     220   1      5      
    6  15    125648 10     160   2      15       
    7  18    125648 10     110   3      6      
    8  52    125648 10     50    4      1       

    9  56   -11152  0      250   1      17      
    10 15   -11152  0      180   2      15      
    11 18   -11152  0      110   3      6       
    12 22   -11152  0      5     4      14      

    13 56   -11152  10     250   1      17      
    14 15   -11152  10     180   2      15      
    15 22   -11152  10     125   3      14      
    16 18   -11152  10     120   4      6 "), header=TRUE)      

第一步:

我有一个等间隔的列表,其间隔被切割为如下形式:

myinterval <- cut_interval(c(15,5,6,1,17,14), length=10)  

我将为您进行翻译。该内容涉及编程。请保留HTML标签,仅进行翻译。

所以我有两个等级:[0,10)和(10,20]

第二步:

我想通过我的v_cut将每个组/类定义为我的两个级别,如下所示:

id v_idn v_seed v_time v_pop v_rank v_perco v_cut
1  15    125648 0      150   1      15      (10,20]
2  17    125648 0      120   2      5       [0,10)
3  18    125648 0      100   3      6       [0,10)
4  52    125648 0      25    4      1       [0,10)

5  17    125648 10     220   1      5       [0,10)
6  15    125648 10     160   2      15      (10,20] 
7  18    125648 10     110   3      6       [0,10)
8  52    125648 10     50    4      1       [0,10)

9  56   -11152  0      250   1      17      (10,20]
10 15   -11152  0      180   2      15      (10,20]
11 18   -11152  0      110   3      6       [0,10)
12 22   -11152  0      5     4      14      (10,20]

13 56   -11152  10     250   1      17      (10,20]
14 15   -11152  10     180   2      15      (10,20]
15 22   -11152  10     125   3      14      (10,20]
16 18   -11152  10     120   4      6       [0,10)

步骤 3 :

我想了解每个组 v_cut 的 x 轴变量 v_rank 的可变性以及 y 轴时间,因此我需要计算 v_rank 值的最小值、平均值、最大值和标准差,类似于以下内容:

ddply(df, .(v_cut,v_time), summarize ,mean = mean(v_rank), min = min(v_rank), max = max(v_rank), sd = sd(v_rank))

结果期望:*
id  v_time MEAN.v_rank ... v_cut
1   0      2.25            (10,20]
2   0      2.42            [0,10)
3   10     2.25            [0,10)
4   10     2.42            (10,20]

我的问题

我不知道如何通过第一步到第二步 :/

是否可以像第三步中的示例那样按 v_cut 进行分组?

是否可以使用 ddply 的“subset”选项来完成相同的操作?

再次感谢你这位伟大的 R 大师提供的帮助!

更新1:

我已经得到了一个答案,可以完成从 step1 到 step2 :

df$v_cut <- cut_interval(df$v_perco,n=10)

我正在使用plyr,但在这种情况下可能有更好的答案?

回答如何从步骤2到步骤3?

更新2:

Brandon Bertelsen用melt + cast给了我一个很好的答案,但现在(为了理解)我想使用plyr和ddply进行相同的操作,但结果不同:

id  v_idn v_time MEAN.v_rank ... v_cut
    1   15   0      2.25            (10,20]
    2   15   10     2.45            (10,20]
    2   17   0      1.52            [0,10)
    2   17   10     2.42            [0,10)
    etc. 

我正在尝试使用类似以下的内容:

r('sumData <- ddply(df, .(v_idn,v_time), summarize,min = min(v_rank),mean =  mean(v_rank), max = max(v_rank), sd=sd(v_rank))')

但是我希望在我的sumData数据框中有v_cut列,如何使用ddply实现?是否有选项可以实现这一点?还是将初始数据框与键值v_idn合并以将v_cut列添加到sumData是唯一的好答案?


1
从dput(head(df),5)获取一些测试数据会有所帮助。 - Brandon Bertelsen
对于更新2:我不确定您是如何计算出2.25的。因为在您的示例表中,当v_idn = 15且v_time = 0时,我们有v_rank n=2,sum=3(1+2),因此平均值应该是sum/n = 1.5。 - Brandon Bertelsen
2个回答

2
您不需要使用plyr,可以使用reshape
## Pull what you need
dfx <- df[c("v_seed", "v_time","v_rank","v_perco")]
## Bring in your cuts
dfx <- data.frame(dfx, ifelse(df$v_perco > 10,"(10,20]", "[0,10)")))
## Rename v_cut
colnames(dfx)[ncol(dfx)] <- "v_cut"       
## Melt it.    
dfx <- melt(dfx, id=c("v_cut", "v_seed", "v_time"))
## Cast it.
dfx <- cast(dfx, v_cut + v_time + v_seed ~ variable, c(mean,min,max,sd))

如果你只想要平均值,则用以下代码替换最后一行:

dfx <- cast(dfx, v_cut + v_time + v_seed ~ variable, mean)

输入"dfx",您将看到一个与您请求的内容相对应的数据帧。


谢谢您的帮助,我正在尝试您的解决方案,但是在“cast”行中遇到了一些问题,“bound”在df数据框中不存在。您是否有关于此函数的良好文档?因为?cast或?melt看起来很晦涩:s - reyman64
哎呀,"bound" 应该是 v_cut。 - Brandon Bertelsen
我不确定您从v_cut中想要什么,提供的切割并不能将其分成10个箱子,而是n=10,意味着10个箱子。我认为您想要的是cut_interval(x, length=10)。 - Brandon Bertelsen
哦,看起来你在ifelse函数上遇到了问题。当v_perco>10时,我在v_cut列中有[0,10]的值,并且是反向的。 - reyman64
是的,它工作了!我用另一个问题和其他类型的结果更新了原帖... - reyman64

2
你只是遇到了语法问题而已:
## Add your cut
df.new <- data.frame(df, ifelse(df$v_perco > 10,"(10,20]", "[0,10)"))
## Rename v_cut
colnames(df.new)[ncol(df.new)] <- "v_cut"   

## Careful here read the note below
df.new <- ddply(df.new, .(v_idn, v_time), function(x) unique(data.frame(
mean =  mean(x$v_rank),
v_cut = x$v_cut
)))

或者:

ddply(df.new, .(v_idn, v_time), summarise, mean=mean(v_rank))

使用".(v_idn, v_time)"告诉ddply,对于每个v_idn和v_time的组合,您希望它计算v_rank的平均值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接