Creating spaghetti plots of eye-tracking data in R
I’ve been working on consolidating all the different R functions I’ve written over the years for plotting my eye-tracking data and creating just one amazing super-function (based on the ggplot2 package) that can do it all. Here’s a first attempt that anybody with the right kind of dataset should be able to use to create plots like the ones below (generated from fake data. The R code that generates the data is included at the end of the post). If you find this code helpful, please consider acknowledging it via the following URL in your paper/presentation to spread the word:
https://hlplab.wordpress.com/2012/02/27/creating-spaghetti-plots-of-eye-tracking-data-in-r/
Here is the R function. See the TODO section for what is not yet implemented. Standard errors are computed via the “se” function that is provided below. See way down below for the code that generates the fake data used to create above plot, plus some sample calls to the spaghetti function. The easiest way to figure out how this function works is to read the comments provided in the function head and to run some of the sample calls provided below. Questions, comments, feature requests welcome!
library(ggplot2) spaghetti = function( # version 0.1 # written by jdegen@bcs.rochester.edu # 01/11/2012 # TODO: # 1. Implement plotting of multiple regions in one plot. Currently only plotting one region at a time (by conditions) is possible. But sometimes we want to plot looks to eg target/competitor/distractor in one plot. # 2. Give users more control over where to add vertical lines. So far, only adding one vertical line relative to one event and another (or group of others) relative to another event. Important is that there's a time column for each of these events. Ideally, you would also have the option of passing a vector of times, where each designates an x intercept. Or a combination of the two. # 3. Add shapevariable as an option (important for writing papers where you can only do black and white prints and you want to use shapes to distinguish conditions). # 4. Add "TimePlot" to vector of meltids so user doesn't have to do it # 5. Generate meltfactors automatically by probing the type of variables in meltids # 6. If errbarvars is NA, create vector automatically by creating vector of all of {color/line/size/facet}variable that aren't NA # assumes that there are no rows where the value in the column coding region that is currently being looked at is empty. ie for ExAnalysis data.frames: rp_RegionType != "" data, meltids=c("TimePlot"), # vector of column names (as strings) to melt the dataset by (i.e. that you want to have the option of plotting by) meltfactors, # the variables in meltids that are factors. Necessary for as.factor(as.character) calls region=c("Target"), # vector of regions - region names must be column names in data colorvariable=NA, # variable you want to assign different colors by colormapping=NA, # a data.frame with two factor columns. One column with name of variable you want to map different colors to. One called "Color" with the color for each factor level. Data.frame row names must be levels of mapping variable, and data.frame must be sorted by mapping variable. linevariable=NA, # variable (column name in data), levels of which you want to plot in different line types. Currently support only for two levels. sizevariable=NA, # variable (column name in data), levels of which you want to plot in different sizes. you can't specify a sizevariable if you haven't specified a linevariable. Currently support only for two levels. facetvariable=NA, # variable (column name in data), levels of which you want to plot in different grids. uses facet_wrap. errbars=TRUE, # plot error bars by default errbarvars=NA, # vector of column names (as strings) in the melted dataset, the combination of which error bars are to be calculated from (only relevant if drawing ribbons/error bars) dataid="DataID", # name of the variable in the data.frame that uniquely codes samples. downsampling assumes that the data.frame is ordered by this variable, and that sample i and sample i+1 are in fact taken at sampling points t and t+1 (where t is the time step defined by the sampling frequency of the tracker, e.g. 4ms is the default for the EyeLink 500) sample=20, # ms to downsample to downsample="down", # down: downsample. bin: bin data into time bins of size sample srate=4, # sampling rate in ms. 4ms is the default for the EyeLink 500 half="both", # only generalized for half="both". if half = "first" or "second", assumes number of trials in my color_gumballs dataset exclude=NA, # don't exclude data by default. if exclude is list of vectors of character strings, interpret character strings as levels of the variables denoted by the names of the list elements and exclude those from data. e.g. exclude=list(Var1=c("a","b"),Var2=c("1")). only works with factors. onset = 100, # time that 0-point of linguistic event of interest should be aligned to, in ms upperlimit = 500, # upper limit on x axis (time in ms) timeAlignVar=NA, # column that contains time variable that you want to align by (ie you want to align at the 0 point of that variable) addOnsetLine=TRUE, # add a vertical line at linguistic event onset addVerticalLine=FALSE, # add a second vertical line at eg mean onset of another event. provide name of that time variable where 0 is the onset of that event, e.g. "Time_rel_stim_Adjective" extraVerticalType="collapsed", # one of "individual" or "collapsed". Either prints mean onset of each level of the additional linguistic event of interest (individual) or overall mean (sollapsed). # onsetReg=c("competitor","target"), # regions that can have been looked to at onset of linguistic event of interest plottype="empirical", # one of "empirical" or "smoothed". The former plots empirical means (without error bars), the latter plots smoothed predicted means based on y~x. If you want to change the formula for the smoother, set form. form=formula("y~x"), # formula to pass to smoother. method = "auto", # method for smoother to use. can be e.g. lm, glm, loess, etc. see stat_smooth for details # aggregateby=FALSE, # if downsample == "bin" and aggregateby is a string, proportions will be computed for timewindows of size sample and aggregated by aggregateby (eg "Subject") analysiswindow=FALSE, # don't plot analysis window by default. when TRUE, not yet generalized. maybe add extra argument of c(window_start,window_end) times, relative to onset of linguistic event of interest? analysisonset=200, extraopts=FALSE, # don't change the text size etc defaults. when TRUE, sets legend text size to 20, axis text size to 15, axis title size to 20, legend background to white, and panel label size to 20 # align="qonset", # figure out if you can generalize this at all xbreakstep=200, # size of tick mark spacing on x-axis plotwidth=800, # width of the plot in pixels plotheight=450, # height of the plot in pixels fname=NA, # file name (quoted). if left NA, generates a filename for pdf that is not generalized fileformat="png", # can be one of "png" or "pdf" showplot=FALSE, # don't print plot by default (save straight to file instead). If TRUE, will both print plot in quartz window and print plot to file graphdir="./", # path to directory where graph will be saved ... ) { setwd(graphdir) # remove data based on specified factor levels if (!is.na(exclude)) { for (e in names(exclude)) { data = data[!data[,e] %in% exclude[[e]],] print(paste("removed levels:",exclude[[e]],"of variable",e)) } print(paste("after removing factor levels:",nrow(data))) } # remove first/second half if (half == "first") { data <- subset(data, TrialNumber <= 120/2) print(paste("after removing second half:",nrow(data))) } if (half == "second") { data <- subset(data, TrialNumber > 120/2) print(paste("after removing first half:",nrow(data))) } # create time variable to plot on x axis and remove samples not in desired time window print(paste("event onset at", onset)) data$TimePlot = data[,timeAlignVar] + onset if (addVerticalLine != FALSE) { data$NewAdj = onset + (data[,timeAlignVar] - data[,addVerticalLine]) } data = subset(data, TimePlot >= 0 & TimePlot <= upperlimit) print(paste("after removing samples before sentence onset and after upper limit:",nrow(data))) if (downsample == "bin") { print(paste("binning into time bins of",sample,"ms")) data$TimePlot <- (data$TimePlot %/% sample) * sample print(paste("after binning data:",nrow(data))) } else { if (downsample == "down") { print(paste("downsampling to",sample,"ms")) data <- data[as.numeric(as.character(data[,"TimePlot"])) %% (sample/srate) == 0,] print(paste("after downsampling:",nrow(data))) } } if (is.na(fname)) { if (fileformat == "png") { fname = "spaghettiplot.png" } else { if (fileformat == "pdf") { fname = "spaghettiplot.pdf" } } } # create a reduced dataset containing only the data you need for (me in meltfactors) { data[,me] = as.factor(as.character(data[,me])) } melted = melt(data,id = meltids,measure=region) melted$value = as.numeric(as.character(melted$value)) i=0 texty=c() if (is.na(errbarvars)) { errbarvars = c(colorvariable,linevariable,sizevariable,facetvariable) errbarvars = errbarvars[!is.na(errbarvars)] } for (v in errbarvars) { if (i==0) { texty=paste(texty,paste("data[,\"",v,"\"]",sep=""),sep="") i=1 } else { texty=paste(texty,paste("data[,\"",v,"\"]",sep=""),sep=",") } } texty=paste("paste(",texty,")",sep="") melted$errbargroup = eval(parse(text=texty)) melted$errbargroup = as.factor(as.character(melted$errbargroup)) # create the base plot if (is.na(facetvariable)) { if (plottype == "empirical") { if (is.na(linevariable)) { agr <- with(melted, aggregate(value,by=list(TimePlot,eval(parse(text=colorvariable)),errbargroup),FUN="mean")) colnames(agr) = c("TimePlot",colorvariable,"errbargroup","value") agr$SE = with(melted, aggregate(value,by=list(TimePlot,eval(parse(text=colorvariable)),errbargroup),FUN="se"))$x agr$YMin = agr$value - agr$SE agr$YMax = agr$value + agr$SE limits = aes(ymin=YMin,ymax=YMax) p = ggplot(agr, aes_string(x="TimePlot",y="value",color=colorvariable)) } else { if (is.na(sizevariable)) { agr <- with(melted, aggregate(value,by=list(TimePlot,eval(parse(text=colorvariable)),eval(parse(text=linevariable)),errbargroup),FUN="mean")) colnames(agr) = c("TimePlot",colorvariable,linevariable,"errbargroup","value") agr$SE = with(melted, aggregate(value,by=list(TimePlot,eval(parse(text=colorvariable)),eval(parse(text=linevariable)),errbargroup),FUN="se"))$x agr$YMin = agr$value - agr$SE agr$YMax = agr$value + agr$SE limits = aes(ymin=YMin,ymax=YMax) p = ggplot(agr, aes_string(x="TimePlot",y="value",color=colorvariable,linetype=linevariable)) } else { agr <- with(melted, aggregate(value,by=list(TimePlot,eval(parse(text=colorvariable)),eval(parse(text=linevariable)),eval(parse(text=sizevariable)),errbargroup),FUN="mean")) colnames(agr) = c("TimePlot",colorvariable,linevariable,sizevariable,"errbargroup","value") agr$SE = with(melted, aggregate(value,by=list(TimePlot,eval(parse(text=colorvariable)),eval(parse(text=linevariable)),eval(parse(text=sizevariable)),errbargroup),FUN="se"))$x agr$YMin = agr$value - agr$SE agr$YMax = agr$value + agr$SE limits = aes(ymin=YMin,ymax=YMax) p = ggplot(agr, aes_string(x="TimePlot",y="value",color=colorvariable,linetype=linevariable,size=sizevariable)) + scale_size_manual(values=c(3,1.5)) } } p = p + geom_line(aes_string(group="errbargroup"),size=I(2)) if (errbars) { p = p + geom_errorbar(limits,linetype=I(1)) } } else { if (is.na(linevariable)) { p = ggplot(melted, aes_string(x="TimePlot",y="value",color=colorvariable)) } else { if (is.na(sizevariable)) { p = ggplot(melted, aes_string(x="TimePlot",y="value",color=colorvariable,linetype=linevariable)) } else { p = ggplot(melted, aes_string(x="TimePlot",y="value",color=colorvariable,linetype=linevariable,size=sizevariable)) } } p = p + stat_smooth(aes_string(group="errbargroup",fill=colorvariable),size=I(1.5),method=method,formula=form) if (!is.na(colormapping)) { p = p + scale_fill_manual(values=colormapping[sort(as.character(unique(melted[,colorvariable]))),]$Color) } } } else { if (plottype == "empirical") { if (is.na(linevariable)) { agr <- with(melted, aggregate(value,by=list(TimePlot,eval(parse(text=colorvariable)),errbargroup,eval(parse(text=facetvariable))),FUN="mean")) colnames(agr) = c("TimePlot",colorvariable,"errbargroup",facetvariable,"value") agr$SE = with(melted, aggregate(value,by=list(TimePlot,eval(parse(text=colorvariable)),errbargroup,eval(parse(text=facetvariable))),FUN="se"))$x agr$YMin = agr$value - agr$SE agr$YMax = agr$value + agr$SE limits = aes(ymin=YMin,ymax=YMax) p = ggplot(agr, aes_string(x="TimePlot",y="value",color=colorvariable)) #+ } else { if (is.na(sizevariable)) { agr <- with(melted, aggregate(value,by=list(TimePlot,eval(parse(text=colorvariable)),eval(parse(text=linevariable)),errbargroup,eval(parse(text=facetvariable))),FUN="mean")) colnames(agr) = c("TimePlot",colorvariable,linevariable,"errbargroup",facetvariable,"value") agr$SE = with(melted, aggregate(value,by=list(TimePlot,eval(parse(text=colorvariable)),eval(parse(text=linevariable)),errbargroup,eval(parse(text=facetvariable))),FUN="se"))$x agr$YMin = agr$value - agr$SE agr$YMax = agr$value + agr$SE limits = aes(ymin=YMin,ymax=YMax) p = ggplot(agr, aes_string(x="TimePlot",y="value",color=colorvariable,linetype=linevariable)) #+ } else { agr <- with(melted, aggregate(value,by=list(TimePlot,eval(parse(text=colorvariable)),eval(parse(text=linevariable)),eval(parse(text=sizevariable)),errbargroup,eval(parse(text=facetvariable))),FUN="mean")) colnames(agr) = c("TimePlot",colorvariable,linevariable,sizevariable,"errbargroup",facetvariable,"value") agr$SE = with(melted, aggregate(value,by=list(TimePlot,eval(parse(text=colorvariable)),eval(parse(text=linevariable)),eval(parse(text=sizevariable)),errbargroup,eval(parse(text=facetvariable))),FUN="se"))$x agr$YMin = agr$value - agr$SE agr$YMax = agr$value + agr$SE limits = aes(ymin=YMin,ymax=YMax) p = ggplot(agr, aes_string(x="TimePlot",y="value",color=colorvariable,linetype=linevariable,size=sizevariable)) + scale_size_manual(values=c(3,1.5)) } } p = p + geom_line(aes(group=errbargroup),size=I(1)) if (errbars) { p = p + geom_errorbar(limits,linetype=I(1)) } } else { if (is.na(linevariable)) { p = ggplot(melted, aes_string(x="TimePlot",y="value",color=colorvariable)) } else { if (is.na(sizevariable)) { p = ggplot(melted, aes_string(x="TimePlot",y="value",color=colorvariable,linetype=linevariable)) } else { p = ggplot(melted, aes_string(x="TimePlot",y="value",color=colorvariable,linetype=linevariable,size=sizevariable)) } } p = p + stat_smooth(aes_string(group="errbargroup",fill=colorvariable),size=I(1.5)) if (!is.na(colormapping)) { p = p + scale_fill_manual(values=colormapping[sort(as.character(unique(melted[,colorvariable]))),]$Color) } } form = as.formula(paste("~",facetvariable,sep="")) p = p + facet_wrap(form) } # extra stuff that's common to all plots if (analysiswindow) { onset = onset + analysisonset } p <- p + scale_y_continuous("Proportion of fixations") + coord_cartesian(ylim=c(0,1)) + scale_x_continuous("Time",breaks=seq(0,upperlimit,by=xbreakstep)) if (addOnsetLine) { p = p + geom_vline(xintercept=onset, colour="black",size=I(1.5),legend=FALSE) } if (!is.na(colormapping)) { p = p + scale_colour_manual(values=colormapping[sort(as.character(unique(melted[,colorvariable]))),]$Color) } if (addVerticalLine != FALSE) { means <- with(data,aggregate(NewAdj, by=list(eval(parse(text=colorvariable))), FUN=mean)) row.names(means) <- means$Group.1 means <- means[order(means$Group.1),] if (extraVerticalType == "individual") { for (i in 1:length(means$x)) { xi <- means$x[i] if (analysiswindow) { xi <- xi + analysisonset } if (!is.na(colormapping)) { co <- as.character(colormapping[as.character(means$Group.1[i]),]$Color) } else { co <- "black" } p <- p + geom_vline(xintercept=xi, colour=I(co),size=I(1.5),legend=FALSE) } } else { if (extraVerticalType == "collapsed") { xi <- mean(means$x) if (analysiswindow) { xi <- xi + analysisonset } p <- p + geom_vline(xintercept=xi, colour="black", size=I(1.5),legend=FALSE) } } } if (extraopts) { p <- p + opts(legend.text = theme_text(size = 20), axis.text.x = theme_text(size=15), axis.text.y = theme_text(size=15,hjust=1), axis.title.x = theme_text(size=20), axis.title.y = theme_text(size=20,angle=90),legend.background=theme_rect(fill="white"),strip.text.x = theme_text(size=15)) } if (showplot) { print(p) } # print plot to file print(paste("printing to",fname)) if (fileformat == "png") { png(file=fname, width=plotwidth, height=plotheight) } else { if (fileformat == "pdf") { pdf(file=fname, width=plotwidth, height=plotheight) } } print(p) dev.off() rm(p) gc() } ########################################## # get standard error ########################################## se <- function(x) { y <- x[!is.na(x)] # remove the missing values, if any sqrt(var(as.vector(y))/length(y)) }
Finally, here is the code that generated the plotted data and some sample calls to spaghetti(), including the ones that generated above plots.
# created by jdegen@bcs.rochester.edu # 02/27/2012 # Before you begin, make sure to find and replace graphdir="/Users/jdegen/Dropbox/spaghettigraphs/" with the path to your own graph directory # generate some fake data of a 2x2 design (contrast present/absent x adjective scalar/color) with four subjects d = data.frame(DataID=seq(1,4000),Subject=factor(levels=c("dartagnan","athos","aramis","porthos"),x=rep(c("dartagnan","athos","aramis","porthos"),each=1000)),Time=rep(seq(20,500,by=20),160),Contrast=factor(levels=c("present","absent"),x=c(rep(rep(c("present","absent"),each=25),4))),Adjective=factor(levels=c("color","scalar"),x=c(rep(rep(c("color","scalar"),each=50),2))),Time_rel_Adjective=rep(c(seq(-80,400,by=20),seq(-100,380,by=20),seq(-120,360,by=20),seq(-140,340,by=20)),40),Time_rel_Noun=rep(c(seq(-420,60,by=20),seq(-400,80,by=20),seq(-380,100,by=20),seq(-400,80,by=20)),40)) # time of adjective/noun onset relative to stimulus onset d$Time_Adjective = d$Time-d$Time_rel_Adjective d$Time_Noun = d$Time-d$Time_rel_Noun # generate looks to target and competitor region d$rp_RegionType = factor(levels=c("target","competitor"),x=NA) d[d$Contrast == "absent" & d$Time_rel_Noun < 50,]$rp_RegionType = rep(sample(x=c("target","competitor"),size=nrow(d[d$Contrast == "absent" & d$Time_rel_Noun < 50,]),replace=TRUE,prob=c(.5,.5))) d[d$Contrast == "absent" & d$Time_rel_Noun >= 50,]$rp_RegionType = rep(sample(x=c("target","competitor"),size=nrow(d[d$Contrast == "absent" & d$Time_rel_Noun >= 50,]),replace=TRUE,prob=c(.8,.2))) d[d$Contrast == "present" & d$Adjective == "scalar" & d$Time_rel_Adjective <= 150,]$rp_RegionType = rep(sample(x=c("target","competitor"),size=nrow(d[d$Contrast == "present" & d$Adjective == "scalar" & d$Time_rel_Adjective <= 150,]),replace=TRUE,prob=c(.5,.5))) d[d$Contrast == "present" & d$Adjective == "scalar" & d$Time_rel_Adjective > 150,]$rp_RegionType = rep(sample(x=c("target","competitor"),size=nrow(d[d$Contrast == "present" & d$Adjective == "scalar" & d$Time_rel_Adjective > 150,]),replace=TRUE,prob=c(.8,.2))) d[d$Contrast == "present" & d$Adjective == "color" & d$Time_rel_Adjective <= 250,]$rp_RegionType = rep(sample(x=c("target","competitor"),size=nrow(d[d$Contrast == "present" & d$Adjective == "color" & d$Time_rel_Adjective <= 250,]),replace=TRUE,prob=c(.5,.5))) d[d$Contrast == "present" & d$Adjective == "color" & d$Time_rel_Adjective > 250,]$rp_RegionType = rep(sample(x=c("target","competitor"),size=nrow(d[d$Contrast == "present" & d$Adjective == "color" & d$Time_rel_Adjective > 250,]),replace=TRUE,prob=c(.8,.2))) # columns coding looks to regions as binary variables d$Target=ifelse(d$rp_RegionType == "target", 1, 0) d$Target = as.factor(as.character(d$Target)) d$Competitor=ifelse(d$rp_RegionType == "competitor", 1, 0) d$Competitor = as.factor(as.character(d$Competitor)) # to get a feel for the dataset summary(d) head(d) # plot looks to target in the contrast present vs. absent condition spaghetti(d,meltids=c("TimePlot","Subject","Contrast","Adjective"),meltfactors=c("Subject","Contrast","Adjective"),colorvariable="Contrast",errbarvars=c("Contrast"),srate=20,graphdir="/Users/jdegen/Dropbox/spaghettigraphs/",timeAlignVar="Time_rel_Adjective",fname="firstplot.png") # remove error bars spaghetti(d,meltids=c("TimePlot","Subject","Contrast","Adjective"),meltfactors=c("Subject","Contrast","Adjective"),graphdir="/Users/jdegen/Dropbox/spaghettigraphs/",timeAlignVar="Time_rel_Adjective",errbarvars=c("Contrast"),srate=20,colorvariable="Contrast",errbars=FALSE) # smoothed plot spaghetti(d,meltids=c("TimePlot","Subject","Contrast","Adjective"),meltfactors=c("Subject","Contrast","Adjective"),timeAlignVar="Time_rel_Adjective",colorvariable="Contrast",errbarvars=c("Contrast"),srate=20,graphdir="/Users/jdegen/Dropbox/spaghettigraphs/",plottype="smoothed") # smoothed linearplot spaghetti(d,meltids=c("TimePlot","Subject","Contrast","Adjective"),meltfactors=c("Subject","Contrast","Adjective"),timeAlignVar="Time_rel_Adjective",colorvariable="Contrast",errbarvars=c("Contrast"),srate=20,graphdir="/Users/jdegen/Dropbox/spaghettigraphs/",plottype="smoothed",method="lm",fname="linearsmooth.png") # change color # color mapping data.frame to pass to function cmap = data.frame(Contrast=c("present","absent"),Color=c("red","blue")) row.names(cmap) <- cmap$Contrast cmap <- cmap[order(cmap$Contrast),] spaghetti(d,meltids=c("TimePlot","Subject","Contrast","Adjective"),meltfactors=c("Subject","Contrast","Adjective"),timeAlignVar="Time_rel_Adjective",colorvariable="Contrast",errbarvars=c("Contrast"),srate=20,graphdir="/Users/jdegen/Dropbox/spaghettigraphs/",plottype="smoothed",colormapping=cmap) # plot different adjective conditions spaghetti(d,meltids=c("TimePlot","Subject","Contrast","Adjective"),meltfactors=c("Subject","Contrast","Adjective"),timeAlignVar="Time_rel_Adjective",colorvariable="Contrast",errbarvars=c("Contrast","Adjective"),srate=20,graphdir="/Users/jdegen/Dropbox/spaghettigraphs/",colormapping=cmap,linevariable="Adjective") # increase bin size to 40ms spaghetti(d,meltids=c("TimePlot","Subject","Contrast","Adjective"),meltfactors=c("Subject","Contrast","Adjective"),timeAlignVar="Time_rel_Adjective",colorvariable="Contrast",errbarvars=c("Contrast","Adjective"),srate=20,graphdir="/Users/jdegen/Dropbox/spaghettigraphs/",colormapping=cmap,linevariable="Adjective",sample=40,downsample="bin") # add second line at mean noun onset spaghetti(d,meltids=c("TimePlot","Subject","Contrast","Adjective"),meltfactors=c("Subject","Contrast","Adjective"),timeAlignVar="Time_rel_Adjective",colorvariable="Contrast",errbarvars=c("Contrast","Adjective"),srate=20,graphdir="/Users/jdegen/Dropbox/spaghettigraphs/",colormapping=cmap,linevariable="Adjective",sample=40,downsample="bin",addVerticalLine="Time_rel_Noun") # add second line at mean noun onset by contrast condition spaghetti(d,meltids=c("TimePlot","Subject","Contrast","Adjective"),meltfactors=c("Subject","Contrast","Adjective"),timeAlignVar="Time_rel_Adjective",colorvariable="Contrast",errbarvars=c("Contrast","Adjective"),srate=20,graphdir="/Users/jdegen/Dropbox/spaghettigraphs/",colormapping=cmap,linevariable="Adjective",sample=40,downsample="bin",addVerticalLine="Time_rel_Noun",extraVerticalType="individual",extraopts=TRUE) # create individual plots by subject spaghetti(d,meltids=c("TimePlot","Subject","Contrast","Adjective"),meltfactors=c("Subject","Contrast","Adjective"),timeAlignVar="Time_rel_Adjective",colorvariable="Contrast",errbarvars=c("Contrast","Adjective"),srate=20,graphdir="/Users/jdegen/Dropbox/spaghettigraphs/",fname="smoothedplot.png",colormapping=cmap,sample=40,downsample="bin",plottype="smoothed",linevariable="Adjective",facetvariable="Subject",extraopts=TRUE) # remove data from one subject spaghetti(d,meltids=c("TimePlot","Subject","Contrast","Adjective"),meltfactors=c("Subject","Contrast","Adjective"),timeAlignVar="Time_rel_Adjective",colorvariable="Contrast",errbarvars=c("Contrast","Adjective"),srate=20,graphdir="/Users/jdegen/Dropbox/spaghettigraphs/",colormapping=cmap,sample=40,downsample="bin",plottype="smoothed",facetvariable="Subject",linevariable="Adjective",exclude=list(Subject=c("dartagnan"),Contrast=c("absent"))) # remove data from subject "dartagnan" and contrast "absent" condition spaghetti(d,meltids=c("TimePlot","Subject","Contrast","Adjective"),meltfactors=c("Subject","Contrast","Adjective"),timeAlignVar="Time_rel_Adjective",colorvariable="Contrast",errbarvars=c("Contrast","Adjective"),srate=20,graphdir="/Users/jdegen/Dropbox/spaghettigraphs/",colormapping=cmap,sample=40,downsample="bin",plottype="smoothed",facetvariable="Subject",linevariable="Adjective",exclude=list(Subject=c("dartagnan"),Contrast=c("absent")))
February 27, 2012 at 3:35 pm
[…] on how to create nice spaghetti plots (proportions of fixations plots) of eye-tracking data in r here. the function code, code for generating fake data, and sample calls to the function for plotting […]
LikeLike
March 15, 2012 at 9:15 am
For some reason the code is showing out of post content
LikeLike
March 15, 2012 at 10:28 am
It does that because there are no line breaks in those lines. I will update the code within the next 5 days to include some of the features mentioned in the TODO list, and I’ll make sure that there are line breaks at the appropriate positions. In the meantime if you copy paste the code, it will copy everything just fine.
LikeLike