如何根据R中的多个条件从大数据帧中提取不同长度的向量
How to extract vectors of different lengths from large dataframe depending on multiple conditions in R
我在 R 中有一个包含 3 列的数据框。它看起来有点像这样:
x id trialNumber
1 1.4788 subj_01 trial010
2 1.4794 subj_01 trial010
3 1.4823 subj_01 trial010
4 1.4845 subj_01 trial010
5 1.4889 subj_01 trial010
6 1.4901 subj_01 trial010
...
20121 -1.3597 subj_03 trial042
20122 -1.3601 subj_03 trial042
20123 -1.3667 subj_03 trial042
20124 -1.3713 subj_03 trial042
20125 -1.3800 subj_03 trial042
20126 -1.3857 subj_03 trial042
我想为 x 创建一个包含多列的新数据框;其中列由 id 和 trialNumber 定义。
id 和 trialNumber 的每个组合的行数各不相同。新数据框中的行数应对应于所有 id 和 trialNumber 组合的最大行数。结果应该是这样的:
x1 x2 ... xi
1.4788 1.5678 ...
1.4794 1.5789 ...
1.4823 1.5984 ...
1.4845 ... ...
1.4889 NA ...
1.4901 NA -1.3713
... ... -1.3800
NA ... -1.3857
新数据框中的 x1 到 xi 应对应于原始数据框中 id 和 trialNumber 的每个唯一组合,例如x1 将对应于所有 x,其中 id == 'subj01' 和 trialNumber == 'trial010'.
id 和 trialNumber 有很多组合,所以我不想手动定义对原始数据框进行子集化的条件。
你可以试试(看完以上评论后的建议):
tapply(df$x, paste0(df$id,df$trialNumber), function(x) data.frame(mean = mean(x), lower_limit = mean(x) - sd(x), upper_limit = mean(x) + sd(x)))
$subj_01trial010
mean lower_limit upper_limit
1 1.484871 1.479965 1.489778
$subj_03trial042
mean lower_limit upper_limit
1 -1.370583 -1.381177 -1.35999
或者使用 aggregate
你会得到一个更好的 outpur 格式:
aggregate(x ~ id + trialNumber, data = df, FUN = function(x) c(mean = mean(x), lower_limit = mean(x) - sd(x), upper_limit = mean(x) + sd(x)))
id trialNumber x.mean x.lower_limit x.upper_limit
1 subj_01 trial010 1.484871 1.479965 1.489778
2 subj_03 trial042 -1.370583 -1.381177 -1.359990
如果您真的想要将试验和受试者的每个组合绑定在一起的 x 列,可以使用以下方法:
#step 1: create vector of x per combination
step1 <- split(dat2$x, list(dat2$trial,dat2$subject))
#calculate max length(to add padding)
max_length <- max(sapply(step1,length))
#make all vectors same length padded with NA
step2 <- lapply(step1, function(x){
length(x) <- max_length
x
})
#combine
res <- do.call(cbind,step2)
res
用于数据生成的代码:
set.seed(100)
dat1 <-expand.grid(trial=sprintf("trial_%.03d",1:10),
subject= sprintf("subj_%.02d",1:3))
dat2 <- dat1[sample(nrow(dat1),1000,T),]
dat2$x <- rnorm(nrow(dat2))
我在 R 中有一个包含 3 列的数据框。它看起来有点像这样:
x id trialNumber
1 1.4788 subj_01 trial010
2 1.4794 subj_01 trial010
3 1.4823 subj_01 trial010
4 1.4845 subj_01 trial010
5 1.4889 subj_01 trial010
6 1.4901 subj_01 trial010
...
20121 -1.3597 subj_03 trial042
20122 -1.3601 subj_03 trial042
20123 -1.3667 subj_03 trial042
20124 -1.3713 subj_03 trial042
20125 -1.3800 subj_03 trial042
20126 -1.3857 subj_03 trial042
我想为 x 创建一个包含多列的新数据框;其中列由 id 和 trialNumber 定义。 id 和 trialNumber 的每个组合的行数各不相同。新数据框中的行数应对应于所有 id 和 trialNumber 组合的最大行数。结果应该是这样的:
x1 x2 ... xi
1.4788 1.5678 ...
1.4794 1.5789 ...
1.4823 1.5984 ...
1.4845 ... ...
1.4889 NA ...
1.4901 NA -1.3713
... ... -1.3800
NA ... -1.3857
新数据框中的 x1 到 xi 应对应于原始数据框中 id 和 trialNumber 的每个唯一组合,例如x1 将对应于所有 x,其中 id == 'subj01' 和 trialNumber == 'trial010'.
id 和 trialNumber 有很多组合,所以我不想手动定义对原始数据框进行子集化的条件。
你可以试试(看完以上评论后的建议):
tapply(df$x, paste0(df$id,df$trialNumber), function(x) data.frame(mean = mean(x), lower_limit = mean(x) - sd(x), upper_limit = mean(x) + sd(x)))
$subj_01trial010
mean lower_limit upper_limit
1 1.484871 1.479965 1.489778
$subj_03trial042
mean lower_limit upper_limit
1 -1.370583 -1.381177 -1.35999
或者使用 aggregate
你会得到一个更好的 outpur 格式:
aggregate(x ~ id + trialNumber, data = df, FUN = function(x) c(mean = mean(x), lower_limit = mean(x) - sd(x), upper_limit = mean(x) + sd(x)))
id trialNumber x.mean x.lower_limit x.upper_limit
1 subj_01 trial010 1.484871 1.479965 1.489778
2 subj_03 trial042 -1.370583 -1.381177 -1.359990
如果您真的想要将试验和受试者的每个组合绑定在一起的 x 列,可以使用以下方法:
#step 1: create vector of x per combination
step1 <- split(dat2$x, list(dat2$trial,dat2$subject))
#calculate max length(to add padding)
max_length <- max(sapply(step1,length))
#make all vectors same length padded with NA
step2 <- lapply(step1, function(x){
length(x) <- max_length
x
})
#combine
res <- do.call(cbind,step2)
res
用于数据生成的代码:
set.seed(100)
dat1 <-expand.grid(trial=sprintf("trial_%.03d",1:10),
subject= sprintf("subj_%.02d",1:3))
dat2 <- dat1[sample(nrow(dat1),1000,T),]
dat2$x <- rnorm(nrow(dat2))