我正在尝试在数据框中创建一个变量,该变量将引用前一行(在正在创建的变量中)来派生一个值。我对R比较陌生,我来自excel,在那里,这种自我引用和迭代更新的特性非常简单。
mydata <- data.frame(trial = c(1,1,1,1,1,1,1,1,2,2),
fixation=c("","","aoi1","aoi1","","aoi3","aoi3","","",""),
trial.marker=c("","","","","","","",1,"",""))
mydata
trial fixation trial.marker
1
1
1 aoi1
1 aoi1
1
1 aoi3
1 aoi3
1 1
2
2 详细背景:这是我拥有的一个更大的眼球跟踪数据集的样本。每行代表一个观察值,每隔约13ms记录一次。固定变量表示试验中受试者在屏幕上观看的那个点。我的目标(现在)是计算每个试验的第一个固定指标(受试者在每个试验中第一个固定的是什么)。我的方法是首先计算一个试验标记来标记每个试验的结束,然后计算第一个固定变量,它将扫描固定变量,寻找"aoi1“或"aoi3”的第一个“命中”,然后一直保留该信息,直到它到达试验结束(试验标记)。然后,我将通过这个试验标记来索引数据帧,为每个试验提取一行摘要。我需要编写各种类型的变量,我知道的最好的方法是计算这些类型的自引用变量。
简短背景:我需要计算一个变量,该变量将检测每个试验的固定变量中包含"aoi1“或"aoi3”的第一个观察值,并将此信息记录在与trial.marker变量中的1值相同的行中。
我使用了shift()函数来计算trial.marker,但是当引用同一变量的前一行时,它不能正常工作。我让它工作的唯一方法是使用一个可怕的for循环:
for (i in 1:nrow(mydata)){
if(i == 1){mydata$first.fixation[i]<- ""}
else if (mydata$trial.marker[i-1]==1){mydata$first.fixation[i]<-""}
else if (mydata$first.fixation[i-1] == ""){
if(mydata$fixation[i] == "aoi1"){mydata$first.fixation[i] <- "aoi1"}
else if (mydata$fixation[i] == "aoi3"){mydata$first.fixation[i] <- "aoi3"}
else mydata$first.fixation[i] <- ""
}
else mydata$first.fixation[i] <- mydata$first.fixation[i-1]
}
mydata
trial fixation trial.marker first.fixation
1
1
1 aoi1 aoi1
1 aoi1 aoi1
1 aoi1
1 aoi3 aoi1
1 aoi3 aoi1
1 1 aoi1
2
2 我正在运行的数据集有120万行,运行它需要大约5个小时,所以我希望有一种计算效率更高的方法来接近它。
如果我的R语言很奇怪和/或我的文章格式很糟糕,我很抱歉。这是我的第一个堆栈溢出post =)希望事情足够清楚,你可以理解我在这里试图做什么。因为我是R的新手,所以我相信也可能会有一种完全不同的方法来解决这个问题,只是我没有想到。但谁知道呢。
发布于 2016-04-12 07:55:35
这是我的机会。请注意,我不是R方面的专家(更多的只是将其用作学习练习),所以我希望其他人能加入进来,或者至少批评我的代码。
我在你的数据中添加了几行,用于我正在进行的检查。它仍然循环,但这一次只是超过了应该更快的试验次数。
理想情况下,您可以避免R中的循环,因为向量化操作几乎总是更快。
mydata <- data.frame(trial = c(1,1,1,1,1,1,1,1,2,2),
fixation=c("","","aoi1","aoi1","","aoi3","aoi3","","aoi3",""),
trial.marker=c("","","","","","","",1,"",""))
mydata
#structure shows it produces factored data (which I don't know enough about to like)
str(mydata)
#To avoid factors use stringsAsFactors = FALSE, also added blank column for first.fixation
mydata <- data.frame(trial = c(1,1,1,1,1,1,1,1,2,2,3,3),
fixation=c("","","aoi1","aoi1","","aoi3","aoi3","","","","aoi3",""),
trial.marker=c("","","","","","","",1,"",2,"",""),
first.fixation="",
stringsAsFactors = FALSE)
mydata
str(mydata)
trials<-unique(mydata$trial)
#which returns the indices that match the criteria, function not used for anything just for demonstration
which(mydata$fixation!="" & mydata$trial==1)
#loop through trials
for (i in 1:length(trials)){
trial<-trials[i]
#If there are no fixation it would error out so if statement
if(length(which(mydata$fixation!="" & mydata$trial==trial))>0){
#Find the last row with the given trial number
rowmax <- max(which(mydata$trial==trial))
#Find the first row with given trial number and fixation
rowmin <- min(which(mydata$fixation!="" & mydata$trial==trial))
#fill the data in
mydata$first.fixation[rowmin:rowmax] = mydata$fixation[rowmin]
}
}
mydata发布于 2016-04-13 20:32:48
我会用data.table来解决这个问题,它通常会提供非常好的性能。虽然我还没有运行一个量的基准测试。这就是解决方案。
library(data.table)
dt <- data.table(mydata)
f <- function(fixation) {
if (length(which(fixation != "")) == 0) {
return(rep("", length(fixation)))
}
min_informed <- min(which(fixation != ""))
return(c(rep("", min_informed-1), rep(fixation[min_informed], length(fixation)-min_informed+1)))
}
dt[, fist.fixation:=f(fixation), by=list(trial)]和输出
trial fixation trial.marker fist.fixation
1: 1
2: 1
3: 1 aoi1 aoi1
4: 1 aoi1 aoi1
5: 1 aoi1
6: 1 aoi3 aoi1
7: 1 aoi3 aoi1
8: 1 1 aoi1
9: 2
10: 2 2
11: 3 aoi3 aoi3
12: 3 aoi3假设您不熟悉data.table,可以解释一下代码:在dt[, fist.fixation:=f(fixation), by=list(trial)]中,第一个参数是查询,在本例中是所有元素,第二个参数是从函数f的结果创建新列first.fixation,第三个参数是按试验=>分组,因此函数f接收一个包含每个试验的所有修正的向量。一旦你有了这个向量,在函数f中,就很容易知道哪个是第一个被通知的,依此类推。
如果你决定为你的大data.frame检查它,如果你把你得到的时间贴出来就好了。我认为这应该需要几分钟的时间(可能需要几分钟)。
不管怎样,我希望它能帮上忙。
发布于 2016-04-14 04:52:54
所以我很确定我用了不同的方法解决了这个问题。输入我的问题让我清楚地知道,我正在寻找一个试验总结,因此我执行了以下操作:
first.match <- function(x,y){
match.list <- sort(match(x,y),decreasing=FALSE)
y[match.list[1]]
}
ff.data <-aggregate(x=exp2data$aoifixation,
by=list(exp2data$subject,exp2data$trial),
FUN=function(x) first.match(c("AOI1","AOI3"),x))这给了我为每个试验总结的第一个固定(通过每个主题;但是在上面的例子中没有显示)。然后,我使用试验标记技术向下索引原始数据集,并将聚合中的第一个固定向量添加到裁剪后的数据集上。
ff.data <- ff.data[order(ff.data$Group.1,ff.data$Group.2),]
exp2data.trial <- exp2data[exp2data$trialmarker==1,]
exp2data.trial$ff <- ff.data[,3]我仍然在三重检查,以确保它的编码正确,但它似乎是好的。最好的部分是它在几秒钟内就跑完了!我还没有尝试过,但我想我可以通过修改聚合的自定义函数,从内部试验数据中获得我需要的所有奇怪的眼睛跟踪变量。
https://stackoverflow.com/questions/36560767
复制相似问题