在R

时间:2015-09-30 22:51:19

标签: r

我正在尝试在大型数据框中编制索引。 sdata框架有300万个观测值和26个变量(在底部)。

setsize <- 6
eccent <- 150
ctrX <- 400
ctrY <- 300

xyrotate <- function(x,y,ctrX,ctrY,angle){
  distX <- x - ctrX;
  distY <- y - ctrY;
  radians <- angle * (pi/180);
  rotX <- ctrX + (distX*cos(radians)) - (distY*sin(radians));
  rotY <- ctrY + (distX*sin(radians)) + (distY*cos(radians));
  coordinates <- list("X" = rotX,"Y" = rotY)
  return(coordinates)
}

loc <- data.frame(x = numeric(setsize),
              y = numeric(setsize))
loc$x[1] <- ctrX
loc$y[1] <- ctrY - eccent
for(i in 2:setsize){
  coord <- xyrotate(loc$x[1], loc$y[1],ctrX,ctrY,(i-1)*(360/setsize)) 
  loc$x[i] <- coord$X
  loc$y[i] <- coord$Y
}
gazedist <- matrix(nrow=nrow(sdata), ncol = setsize)
for(d in 1:setsize){
  x <- sdata$RIGHT_GAZE_X-loc$x[d]
  y <- sdata$RIGHT_GAZE_Y-loc$y[d]
  gazedist[,d] <- sqrt(x^2+y^2)
}
sdata$gdist_T <- 0
sdata$gdist_T <- gazedist[ ,sdata$t_targLoc]

此处的最后一行导致R崩溃。有没有办法将sdata $ t_targLoc [i]的值插入到gazedistance [i,d]的d值中。 for循环等价物是:

for(i in 1:length(gazedist)){
   sdata$gdist_T[i] <- gazedist[i,sdata$t_targLoc[i]]
}

但是在R ......中这会很慢......

sdata结构

structure(list(RIGHT_GAZE_X = c(409.5, 409.6, 409.5, 409.4, 409.3, 
409.2, 409.1, 409, 408.9, 408.8), RIGHT_GAZE_Y = c(291.9, 291.5, 
290.9, 290.3, 290.3, 290.3, 289.8, 289.2, 288.7, 288.8), RECORDING_SESSION_LABEL = structure(c(1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "ET101", class = "factor"), 
    t_block = c(3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), t_trialNum = c(129L, 
    129L, 129L, 129L, 129L, 129L, 129L, 129L, 129L, 129L), t_subjNum = c(101L, 
    101L, 101L, 101L, 101L, 101L, 101L, 101L, 101L, 101L), t_colCond = structure(c(1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "green", class = "factor"), 
    t_targLoc = c(3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), t_targID = structure(c(1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "L", class = "factor"), 
    t_targShape = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L), .Label = "diamond", class = "factor"), t_singLoc = c(5L, 
    5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L), t_singPres = structure(c(1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "P", class = "factor"), 
    t_singDist = c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), t_singAngle = c(120L, 
    120L, 120L, 120L, 120L, 120L, 120L, 120L, 120L, 120L), t_targAngle = c(120L, 
    120L, 120L, 120L, 120L, 120L, 120L, 120L, 120L, 120L), t_RESP = structure(c(1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "L", class = "factor"), 
    t_ACC = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), t_RT = c(686.1062, 
    686.1062, 686.1062, 686.1062, 686.1062, 686.1062, 686.1062, 
    686.1062, 686.1062, 686.1062), TRIAL_START_TIME = c(1031031L, 
    1031031L, 1031031L, 1031031L, 1031031L, 1031031L, 1031031L, 
    1031031L, 1031031L, 1031031L), TIMESTAMP = c(1031030, 1031032, 
    1031034, 1031036, 1031038, 1031040, 1031042, 1031044, 1031046, 
    1031048), IP_START_TIME = c(1031031L, 1031031L, 1031031L, 
    1031031L, 1031031L, 1031031L, 1031031L, 1031031L, 1031031L, 
    1031031L), currtime = c(0, 2, 4, 6, 8, 10, 12, 14, 16, 18
    ), currsamp = c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), gdist_T = c(0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0), gdist_S = c(0, 0, 0, 0, 0, 0, 
    0, 0, 0, 0), gdist_NS = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)), .Names = c("RIGHT_GAZE_X", 
"RIGHT_GAZE_Y", "RECORDING_SESSION_LABEL", "t_block", "t_trialNum", 
"t_subjNum", "t_colCond", "t_targLoc", "t_targID", "t_targShape", 
"t_singLoc", "t_singPres", "t_singDist", "t_singAngle", "t_targAngle", 
"t_RESP", "t_ACC", "t_RT", "TRIAL_START_TIME", "TIMESTAMP", "IP_START_TIME", 
"currtime", "currsamp", "gdist_T", "gdist_S", "gdist_NS"), row.names = 53170:53179, class = "data.frame")

3 个答案:

答案 0 :(得分:2)

您似乎想要抓住sdist$$t_targLoc[i]的第i行和gazedist列。有一个内置的。使用:

sdata$gdist_T <- gazedist[cbind(1:nrow(gazedist),sdata$t_targLoc)]

以下是一个例子:

m <- matrix(1:25,nc=5)
m
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    1    6   11   16   21
# [2,]    2    7   12   17   22
# [3,]    3    8   13   18   23
# [4,]    4    9   14   19   24
# [5,]    5   10   15   20   25
v <- c(1,3,5,2,4)
m[cbind(1:5,v)]
# [1]  1 12 23  9 20

BTW,您的第一个for循环可以替换为:

loc <- as.data.frame(xyrotate(ctrX,ctrY-eccent, ctrX,ctrY,(1:(setsize-1))*360/setsize))
loc <- rbind(c(X=ctrX,Y=ctrY-eccent),lloc)

您的第二个for循环可以替换为,例如,

f <- function(x,y) {
  x <- sdata$RIGHT_GAZE_X-x
  y <- sdata$RIGHT_GAZE_Y-y
  sqrt(x^2+y^2)
}
ggazedist <- mapply(f, loc$x, loc$y)
identical(gazedist,ggazedist)
# [1] TRUE

答案 1 :(得分:1)

是的,我觉得这很有效。基本上,您希望从矩阵中获取向量,其中行索引为1:nrow(sdat),列索引为sdata$t_targLoc。这不是内置的(我知道),但我们可以将矩阵转换为矢量并获取正确的值。

gazedist_vals = as.vector(gazedist)
rows = 1:nrow(sdat)
cols = sdat$t_targLoc
indices = (cols - 1) * nrow(gazedist) + rows
sdata$gdist_T = gazedist_vals[indices]

我认为这会做你想要的。

您的数据摘录并未说明这一点,因为t_targLoc始终是3.这里有一点说明:

x = matrix(c(5,2,65,8,4,2), nrow = 2)
x
#      [,1] [,2] [,3]
# [1,]    5   65    4
# [2,]    2    8    2
as.vector(x)
# [1]  5  2 65  8  4  2
rows = c(1, 1, 2)
cols = c(3,2,1)
inds = (cols - 1) * nrow(x) + rows
as.vector(x)[inds]
# [1]  4 65  2

一条评论:您的问题是彻底的,但 minimal 示例通常更可取。你给了我们26列数据,其中只有一列是必需的。你给了我们函数和代码来计算距离,当你刚刚给出一个距离矩阵(然后只需要一个数据列)。像我的x矩阵以及rowscols向量这样的小例子可能就是您展示问题所需的全部内容。

答案 2 :(得分:0)

你可以,但我怀疑你会节省很多时间,除非你找到一种完全矢量化的方法。换句话说,你必须避免使用像apply或sapply这样的函数,这些函数都基于C中的for循环,因此,如果有的话,循环的速度不会比正常快。

someFunction <- function(x) ifelse(x %in% seq(0, 50000, 100), 1, 0)

# Here you have "vectorized" the indexing
system.time(sapply(1:nrow(diamonds), someFunction))
# 2.6 elapsed secs

## vs here where you're just using a for loop

system.time(
for(i in 1:nrow(diamonds)) {
  k[i] <- someFunction(i)
}
)
# 2.7 elapsed secs