最近,我一直在使用包含各种类型的多维数据的数据结构 . 就我而言,数组中的主题录音包含以下维度:

  • 主题ID(dim = 9)

  • 型号(昏暗= 8)

  • 试验(昏暗= 30)

  • 每次试用样品(昏暗= 30)

在实验期间,受试者从前15个试验的分布A接收数据,然后在最后15个试验中接收分布B,反之亦然 . 这在我的数据中表示为“AB”组或“BA”组 . 受试者1,3,4,5,7,8,9在AB组中,受试者2,6在BA组中 .

我经常想要遍历所有这些信息以查找摘要统计信息,将其作为数据帧格式化为长格式,然后将其提供给ggplot . 通常,我最终会在进程中使用一些嵌套结构,然后我必须使用嵌套的 lapply 进行循环 . 以下是我过去设置此类数据的方法 . 在此可再现示例中,将随机数组的样本主题记录分配给 recordings 变量 .

在此代码中,我计算每个主题(1:9)在每个分布上的平均值和标准差("A"或"B",每个15个试验) . rbind 用于将数据融合成长格式(不知道如何在我的情况下用 reshape2::melt 实现相同的效果) . 然后使用额外的列手动注释数据以供ggplot使用 . 其中一列("group")指定来自哪些主题的主题("AB"或"BA") .

subj <- 1:9
nTrials <- 30
distr <- list(1:(nTrials/2), (nTrials/2 +1):nTrials)
model <- 5
size <- (nTrials * length(subj)) * 2
recordings <- array(rnorm(64800), dim = c(9,8,30,30))

dat1 <-
  lapply(distr, function(x) lapply(subj, function(y) recordings[y, model, x, ] %>% t()) %>% 
           lapply(., function(z) {
             as.data.frame(z) %>%  
               mutate(mean = rowMeans(.),
                      sd = apply(., 1, sd)) %>%
               select(mean, sd)
           }) %>%
           do.call(rbind, .)) %>% 
  do.call(rbind, .) %>% 
  mutate(distribution = c(rep("A", size/2), rep("B", size/2)),
         time = rep(seq(0, 2.9, 0.1), length(subj)*2),
         subject = rep(subj, each = nTrials) %>% rep(., 2),
         group = rep(c("AB", "BA", "AB", "AB", "AB", "BA", "AB", "AB", "AB"), each = nTrials) %>% rep(., 2)) %>%
  set_colnames(c("mean", "se", "distribution", "time", "subject", "group"))

ggplot(dat1, aes(time, mean, ymin = mean-se, ymax = mean+se, color = distribution)) +
  geom_line() +
  geom_errorbar() +
  geom_hline(yintercept = 0, linetype = "dashed") +
  facet_wrap(group ~ subject) +
  xlab("Time (sec)") +
  ylab("Recording") +
  scale_color_manual(values = c("red3", "blue3")) +
  theme_bw()

好吧,但是如果我想将数据压缩到具有两个方面的图表中,AB在一个方面的所有主题的平均值和标准差以及另一个方面的BA中所有主题的平均值和标准差怎么办?

这是我之前所知,我仍然不得不将它包装在 distr 列表的另一个lapply中,以及AB或BA中的主题的另一个包装!嵌套开始变得荒谬,我的代码已经很难阅读了 .

subjBA <- c(2,6)            
subjAB <- c(1,3,4,5,7,8,9)   
subj.l <- list(subjHL, subjLH) 

# To do:
# Replace distr[[1]] with an lapply loop over both list elements of distr
# Replace subj.l[[1]] with an lapply loop over both list elements of subj.l

lapply(subj.l[[1]], function(y) recordings[y, M, distr[[1]],] %>% t()) %>% 
  lapply(., function(z) {
    as.data.frame(z) %>%  
      mutate(mean = rowMeans(.),
             sd = apply(., 1, sd)) %>%
      select(mean, sd) %>%
      do.call(rbind, .) 
  }) %>% 
  do.call(rbind,. ) %>%
  split(., rownames(.)) %>%
  lapply(., function(b) matrix(b, nrow = 4) %>% 
  colMeans())

当然有更好的方法来做到这一点!在基础R( aggregate ?),dplyr或其他可能使这种过程更简单的包中有汇总函数吗?我之前没有使用过 data.table 但如果这是最干净的解决方案,我可能会咬紧牙关并强迫自己学习 .