如何根据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))