如何将数据框中的条目分配给不同的组?

时间:2012-06-20 14:29:59

标签: r grouping dataframe

所以,在我的df中有一个专栏,其中列出了我为实验测试的所有科目。条目被编码为具有x级别的因子。每个受试者已经过两次测试,因为df中每个受试者有两个数据集。这些数据集可以具有不同的长度。现在我需要按照测试时间(1或2)对主题进行分组,这样我就可以将时间作为固定效果包含在我的模型中。我怎么能这样做?

这是我的小例子df:

require("stringr")
>Subject<- c("DG_120204", "DG_120204", "DG_120305", "BZ_120407", "BZ_120506", "BZ_120506",     "BZ_120506", "SN_120310", "SN_120412")
s2<- str_extract(Subject, "\\d{6}")
dates<-as.Date(s2, format="%y%m%d") 
df<-data.frame(Subject, dates)


    Subject      dates
1 DG_120204 2012-02-04
2 DG_120204 2012-02-04
3 DG_120305 2012-03-05
4 BZ_120407 2012-04-07
5 BZ_120506 2012-05-06
6 BZ_120506 2012-05-06
7 BZ_120506 2012-05-06
8 SN_120310 2012-03-10
9 SN_120412 2012-04-12

例如,主题DG的前2个条目来自测试会话1,第三行是会话2,第4行是主题BZ的会话1,第5行是BZ的会话2,依此类推。

我的想法是添加另一个因子列(df $ time)并根据df $ Subject的级别(以及df $ dates中的日期值?)填充1和2。但是现在我甚至没有那么远。

所以我应该有这样的事情:

    Subject      dates time
1 DG_120204 2012-02-04    1
2 DG_120204 2012-02-04    1
3 DG_120305 2012-03-05    2
4 BZ_120407 2012-04-07    1
5 BZ_120506 2012-05-06    2
6 BZ_120506 2012-05-06    2
7 BZ_120506 2012-05-06    2
8 SN_120310 2012-03-10    1
9 SN_120412 2012-04-12    2

我知道这是另一个非常基本的问题,请耐心等待!我最终会学到这个......

3 个答案:

答案 0 :(得分:2)

如果我正确地读取您的数据,每个唯一的2个字符标识符是一个主题,每个唯一的6位数字是差异试验,对吗?如果是这样,这个问题是为colsplit量身定制的。

> cbind(df, colsplit(df$Subject, '_', c('Subject_ID', 'Trial')))
    Subject      dates Subject_ID  Trial
1 DG_120204 2012-02-04         DG 120204
2 DG_120204 2012-02-04         DG 120204
3 DG_120305 2012-03-05         DG 120305
4 BZ_120407 2012-04-07         BZ 120407
5 BZ_120506 2012-05-06         BZ 120506
6 BZ_120506 2012-05-06         BZ 120506
7 BZ_120506 2012-05-06         BZ 120506
8 SN_120310 2012-03-10         SN 120310
9 SN_120412 2012-04-12         SN 120412
> 

现在您已准备好使用主题ID和试用号。

答案 1 :(得分:2)

您可以为主题添加列 (目前,它显然只是第一列的子串), 然后添加一个列,指示它是否是新日期(1)或不是(0), 然后只是累计计算日期变化。

df$id <- str_replace(df$Subject, "_.*", "") 
library(plyr)
df <- df[ order(df$Subject), ]
ddply(df, "id", mutate, 
  new  = c(1, dates[-1] != dates[-length(dates)]), 
  time = cumsum(new)
)

#     Subject      dates id new time
# 1 BZ_120407 2012-04-07 BZ   1    1
# 2 BZ_120506 2012-05-06 BZ   1    2
# 3 BZ_120506 2012-05-06 BZ   0    2
# 4 BZ_120506 2012-05-06 BZ   0    2
# 5 DG_120204 2012-02-04 DG   1    1
# 6 DG_120204 2012-02-04 DG   0    1
# 7 DG_120305 2012-03-05 DG   1    2
# 8 SN_120310 2012-03-10 SN   1    1
# 9 SN_120412 2012-04-12 SN   1    2

答案 2 :(得分:0)

split()for循环的组合可以解决问题:

require("stringr")
Subject<- c("DG_120204", "DG_120204", "DG_120305", "BZ_120407", "BZ_120506",
"BZ_120506", "BZ_120506", "SN_120310", "SN_120412")
s2 <- str_extract(Subject, "\\d{6}")
dates<-as.Date(s2, format="%y%m%d") 
df <- data.frame(Subject, dates)

# Add categorical variable:
spl <- split(df, f=df$Subject)
times <- 1:length(spl)
for(x in seq(along=times)) {
    spl[[x]]$time <- times[x]
}
df <- unsplit(spl, f=df$Subject)

# Sort based of 'Subject' column: 
df <- df[order(df$Subject),]
> df
    Subject      dates time
4 BZ_120407 2012-04-07   1
5 BZ_120506 2012-05-06   2
6 BZ_120506 2012-05-06   2
7 BZ_120506 2012-05-06   2
1 DG_120204 2012-02-04   3
2 DG_120204 2012-02-04   3
3 DG_120305 2012-03-05   4
8 SN_120310 2012-03-10   5
9 SN_120412 2012-04-12   6