如何用ggplot2绘制R中的peristimulus时间直方图(PSTH)

时间:2011-08-15 20:45:49

标签: r ggplot2 neuroscience

说我有两个条件,'a'和'b'。神经元在条件'a'中平均发射40个尖峰/秒(Hz),在条件'b'中发射80个尖峰/秒。对条件“a”的响应呈现20次,条件“b”呈现10次,每次呈现1000ms。

AB <- rbind(
    ldply( 1:20, 
        function(trial) { 
          data.frame( 
              trial=trial, 
              cond=factor('a',c('a','b')), 
              spiketime = runif(40,0,1000))
        }
    ), ldply(21:30, 
        function(trial) {
          data.frame(
              trial=trial, 
              cond=factor('b',c('a','b')), 
              spiketime = runif(80,0,1000))
        }
  )
)

可以用以下方式绘制简单的直方图:

qplot(spiketime, data=AB, geom='line',stat='bin',y=..count.., 
      xlim=c(0,1000), colour=cond, binwidth=100,xlab='Milliseconds')

然而,这不会对演示文稿进行平均,因此,y轴上的值大致相同。我想绘制沿y轴的尖峰率(尖峰/秒),这表明条件'b'每秒引发大约两倍的尖峰。随着演示数量的增加,尖峰率不会增加,它会变得不那么嘈杂。有没有办法在不预先处理数据帧AB的情况下执行此操作?

换句话说,我可以按照以下方式做点什么:

qplot(spiketime, data=AB, geom='line',stat='bin',
      y=..count../num_presentations*1000/binwidth, ylab='Spikes per second',
      xlim=c(0,1000), colour=cond, binwidth=100,xlab='Milliseconds')

其中num_presentations对于条件'a'为20,对于条件'b'为10,而1000 / binwidth只是一个常量以使单位正确?

2 个答案:

答案 0 :(得分:2)

它不是平均条件;它总结了他们。由于条件a具有20×40 = 800点并且条件b具有10 * 80 = 800点,因此这些“直方图”下的“区域”将是相同的。您希望每个试验在一个条件下具有相同的权重,而不是每个点具有相同的权重。这必须作为预处理步骤来完成。

trial.group <- unique(AB[,c("trial","cond")])
hists <- dlply(AB, .(trial), function(x) {hist(x$spiketime, breaks=10, plot=FALSE)})
hists.avg <- ddply(trial.group, .(cond), function(x) {
  hist.group <- ldply(hists[x$trial], function(y) {
    data.frame(mids=y$mids, counts=y$counts)
  })
  ddply(hist.group, .(mids), summarise, counts=mean(counts))
})

ggplot(data=hists.avg, aes(x=mids, y=counts, colour=cond)) + geom_line()

这是使用hist分别对每个试验的数据进行分区,然后对试验组的计数进行平均。这给每个条件赋予相同的权重,并且每个试验在每个条件下都相等。

编辑1:

采用@kohske解决方案,但计算试验次数而不是明确输入:

tmp <- as.data.frame(table(unique(AB[,c("trial","cond")])["cond"]))
names(tmp) <- c("cond","ntrial")
AB <- merge(AB, tmp)

ggplot(AB, aes(spiketime, ntrial=ntrial, colour=cond)) + 
  stat_bin(aes(y=..count../ntrial*1000/100), binwidth=100, geom="line", position="identity") +
  xlim(0,1000) + 
  labs(x='Milliseconds', y="Firing rate [times/s]")

答案 1 :(得分:2)

这是一个错觉:

AB$ntrial <- ifelse(AB$cond=="a", 20, 10)
ggplot(AB, aes(spiketime, ntrial=ntrial, colour=cond)) + 
  stat_bin(aes(y=..count../ntrial*1000/100), binwidth=100, geom="line", position="identity") +
  xlim(0,1000) + 
  labs(x='Milliseconds', y="Firing rate [times/s]")