ggplot2中的topoplot - 例如脑电数据 [英] topoplot in ggplot2 – 2D visualisation of e.g. EEG data

查看:1012
本文介绍了ggplot2中的topoplot - 例如脑电数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可以使用 ggplot2 来产生所谓的 topoplot (通常用于神经科学)?





样本数据:

 标签xy信号
1 R3 0.64924459 0.91228430 2.0261520
2 R4 0.78789621 0.78234410 1.7880972
3 R5 0.93169511 0.72980685 0.9170998
4 R6 R6 0.48406513 0.82383895 3.1933129



更新2(2016年1月27日)



我试过@ alexforrence的完整数据方法,结果如下:



这是一个很好的开始,但有几个问题:


  1. 最后一次调用( ggplot())在Intel i7 4790K上大约需要40秒,而Matlab工具箱几乎可以立即生成这些内容;上面提到的'紧急解决方案'需要大约一秒的时间。

  2. 正如您所看到的,中央部分的上下边界似乎是切片 - 我不确定是什么原因这可能是第三个问题。

  3. 我收到这些警告:

      1:删除了包含非有限值(stat_contour)的170235行。 
    2:删除包含非有限值(stat_contour)的170235行。




更新3(2016年1月27日) h2>

使用不同的 interp(xo,yo) stat_contour(binwidth) values:





如果选择低 interp(xo,yo),在这种情况下 xo / yo = seq(0,1,length = 100)



解决方案

这是一个潜在的开始:首先,我们将附加一些包。我使用






通过评论中提到的改进(设置 extrap = TRUE linear = FALSE interp 调用中填写空位并分别进行样条平滑,然后在绘制之前去除NAs),我们得到:






mgcv 可以做球形样条。这取代了 akima (包含interp()的块不是必需的)。

  spl1 < -  gam(信号〜s(x,y,bs ='sos'),data = dat)
#细网格,粗更快
datamat2 < - data.frame(expand.grid(x = seq(0,1,0.001),y = seq(0,1,0.001)))
resp< - 预测(spl1,datmat2, type =response)
datmat2 $ value< - resp


Can ggplot2 be used to produce a so-called topoplot (often used in neuroscience)?

Sample data:

   label          x          y     signal
1     R3 0.64924459 0.91228430  2.0261520
2     R4 0.78789621 0.78234410  1.7880972
3     R5 0.93169511 0.72980685  0.9170998
4     R6 0.48406513 0.82383895  3.1933129

Full sample data.

Rows represent individual electrodes. Columns x and y represent the projection into 2D space and the column signal is essentially the z-axis representing voltage measured at a given electrode.

stat_contour doesn't work, apparently due to unequal grid.

geom_density_2d only provides a density estimation of x and y.

geom_raster is one not fitted for this task or I must be using it incorrectly since it quickly runs out of memory.

Smoothing (like in the image on the right) and head contours (nose, ears) aren't necessary.

I want to avoid Matlab and transforming the data so that it fits this or that toolbox… Many thanks!

Update (26 January 2016)

The closest I've been able to get to my objective is via

library(colorRamps)
ggplot(channels, aes(x, y, z = signal)) + stat_summary_2d() + scale_fill_gradientn(colours=matlab.like(20))

which produces an image like this:

Update 2 (27 January 2016)

I've tried @alexforrence's approach with full data and this is the result:

It's a great start but there is a couple of issues:

  1. The last call (ggplot()) takes about 40 seconds on an Intel i7 4790K while Matlab toolboxes manage to generate these almost instantly; my ‘emergency solution’ above takes about a second.
  2. As you can see, the upper and lower border of the central part appear to be ‘sliced’ – I'm not sure what causes this but it could be the third issue.
  3. I'm getting these warnings:

    1: Removed 170235 rows containing non-finite values (stat_contour). 
    2: Removed 170235 rows containing non-finite values (stat_contour). 
    

Update 3 (27 January 2016)

Comparison between two plots produced with different interp(xo, yo) and stat_contour(binwidth) values:

Ragged edges if one chooses low interp(xo, yo), in this case xo/yo = seq(0, 1, length = 100):

解决方案

Here's a potential start:

First, we'll attach some packages. I'm using akima to do linear interpolation, though it looks like EEGLAB uses some sort of spherical interpolation here? (the data was a little sparse to try it).

library(ggplot2)
library(akima)
library(reshape2)

Next, reading in the data:

dat <- read.table(text = "   label          x          y     signal
1     R3 0.64924459 0.91228430  2.0261520
2     R4 0.78789621 0.78234410  1.7880972
3     R5 0.93169511 0.72980685  0.9170998
4     R6 0.48406513 0.82383895  3.1933129")

We'll interpolate the data, and stick that in a data frame.

datmat <- interp(dat$x, dat$y, dat$signal, 
                 xo = seq(0, 1, length = 1000),
                 yo = seq(0, 1, length = 1000))
datmat2 <- melt(datmat$z)
names(datmat2) <- c('x', 'y', 'value')
datmat2[,1:2] <- datmat2[,1:2]/1000 # scale it back

I'm going to borrow from some previous answers. The circleFun below is from Draw a circle with ggplot2.

circleFun <- function(center = c(0,0),diameter = 1, npoints = 100){
  r = diameter / 2
  tt <- seq(0,2*pi,length.out = npoints)
  xx <- center[1] + r * cos(tt)
  yy <- center[2] + r * sin(tt)
  return(data.frame(x = xx, y = yy))
}

circledat <- circleFun(c(.5, .5), 1, npoints = 100) # center on [.5, .5]

# ignore anything outside the circle
datmat2$incircle <- (datmat2$x - .5)^2 + (datmat2$y - .5)^2 < .5^2 # mark
datmat2 <- datmat2[datmat2$incircle,]

And I really liked the look of the contour plot in R plot filled.contour() output in ggpplot2, so we'll borrow that one.

ggplot(datmat2, aes(x, y, z = value)) +
  geom_tile(aes(fill = value)) +
  stat_contour(aes(fill = ..level..), geom = 'polygon', binwidth = 0.01) +
  geom_contour(colour = 'white', alpha = 0.5) +
  scale_fill_distiller(palette = "Spectral", na.value = NA) + 
  geom_path(data = circledat, aes(x, y, z = NULL)) +
  # draw the nose (haven't drawn ears yet)
  geom_line(data = data.frame(x = c(0.45, 0.5, .55), y = c(1, 1.05, 1)), 
            aes(x, y, z = NULL)) +
  # add points for the electrodes
  geom_point(data = dat, aes(x, y, z = NULL, fill = NULL), 
             shape = 21, colour = 'black', fill = 'white', size = 2) +
  theme_bw()


With improvements mentioned in the comments (setting extrap = TRUE and linear = FALSE in the interp call to fill in gaps and do a spline smoothing, respectively, and removing NAs before plotting), we get:


mgcv can do spherical splines. This replaces akima (the chunk containing interp() isn't necessary).

library(mgcv)
spl1 <- gam(signal ~ s(x, y, bs = 'sos'), data = dat)
# fine grid, coarser is faster
datmat2 <- data.frame(expand.grid(x = seq(0, 1, 0.001), y = seq(0, 1, 0.001)))
resp <- predict(spl1, datmat2, type = "response")
datmat2$value <- resp

这篇关于ggplot2中的topoplot - 例如脑电数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆