2013-03-08 129 views
4

數據幀的ř2D分級我有通常看起來像這樣繼發覆雜的計算

df.data <- data.frame(x=sample(1:9, 10, replace = T), y=sample(1:9, 10, replace=T), vx=sample(-1:1, 10, replace=T), vy=sample(-1:1, 10, replace=T)) 

x和y的數據幀是位置。 vx和vy是2d矢量的x,y值。我想根據x和y值取這個數據框和「bin」,但是要對vx和vy進行計算。這個函數除了使用一個對我的數據集來說太慢的循環外,

slowWay <- function(df) 
{ 
    df.bin <- data.frame(expand.grid(x=0:3, y=0:3, vx=0, vy=0, count=0)) 

    for(i in 1:nrow(df)) 
    { 
     x.bin <- floor(df[i, ]$x/3) 
     y.bin <- floor(df[i, ]$y/3) 
     print(c(x.bin, y.bin)) 

     df.bin[df.bin$x == x.bin & df.bin$y == y.bin, ]$vx = df.bin[df.bin$x == x.bin & df.bin$y == y.bin, ]$vx + df[i, ]$vx 
     df.bin[df.bin$x == x.bin & df.bin$y == y.bin, ]$vy = df.bin[df.bin$x == x.bin & df.bin$y == y.bin, ]$vy + df[i, ]$vy 
     df.bin[df.bin$x == x.bin & df.bin$y == y.bin, ]$count = df.bin[df.bin$x == x.bin & df.bin$y == y.bin, ]$count + 1 
    } 

    return(df.bin) 
} 

這種類型的二維裝倉可能以非循環的方式嗎?

回答

2

這裏的另一種更快的方式做到這一點,一個包括無人居住倉組合:

fasterWay <- function(df.data) { 
    a1 <- aggregate(df.data[,3:4], list(x=floor(df.data$x/3), y=floor(df.data$y/3)), sum) 
    a2 <- aggregate(list(count=rep(NA,nrow(df.data))), list(x=floor(df.data$x/3), y=floor(df.data$y/3)), length) 
    result <- merge(expand.grid(y=0:3,x=0:3), merge(a1,a2), by=c("x","y"), all=TRUE) 
    result[is.na(result)] <- 0 
    result <- result[order(result$y, result$x),] 
    rownames(result) <- NULL 
    result 
} 

它給我:

x y vx vy count 
1 0 0 0 0  1 
2 0 1 0 0  0 
3 0 2 -1 -1  1 
4 0 3 0 0  0 
5 1 0 -1 -1  1 
6 1 1 0 0  0 
7 1 2 0 0  0 
8 1 3 -1 0  2 
9 2 0 -1 -1  1 
10 2 1 0 0  0 
11 2 2 -1 1  2 
12 2 3 0 0  1 
13 3 0 0 0  0 
14 3 1 0 0  0 
15 3 2 -1 0  1 
16 3 3 0 0  0 
+0

感謝您的回答。完美的作品。其實更好。我不需要0計數的行,它們只是我做事的方式的產物。 – robbie 2013-03-11 14:20:05

1

這是一種方法,但可能需要做一對夫婦的步驟,如果你想完整記錄與無人居住倉組合:

> by(df.data[, c("vx", "vy")],  # input data 
    list(x.bin=floor(df.data$x/3), y.bin=floor(df.data$y/3)), # grouping 
    function(df) sapply(df, function(x) c(Sum=sum(x), Count=length(x)))) #calcs 
x.bin: 0 
y.bin: 1 
     vx vy 
Sum 0 1 
Count 1 1 
--------------------------------------------------------------------- 
x.bin: 1 
y.bin: 1 
     vx vy 
Sum 0 1 
Count 2 2 
--------------------------------------------------------------------- 
x.bin: 2 
y.bin: 1 
     vx vy 
Sum -1 -2 
Count 2 2 
--------------------------------------------------------------------- 
x.bin: 0 
y.bin: 2 
     vx vy 
Sum 1 0 
Count 1 1 
--------------------------------------------------------------------- 
x.bin: 1 
y.bin: 2 
NULL 
--------------------------------------------------------------------- 
x.bin: 2 
y.bin: 2 
     vx vy 
Sum 2 1 
Count 4 4 
1

這裏是一個data.table版本:

library(data.table) 
dt.data<-as.data.table(df.data) # Convert to data.table 
dt.data[,c("x.bin","y.bin"):=list(floor(x/3),floor(y/3))] # Add bin columns 
setkey(dt.data,x.bin,y.bin) 

dt.bin<-CJ(x=0:3, y=0:3) # Cross join to create bin combinations 
dt.data.2<-dt.data[dt.bin,list(vx=sum(vx),vy=sum(vy),count=.N)] # Join the bins and data; sum vx/vy and count matching rows 
dt.data.2[is.na(vx),vx:=0L] # Replace NA with 0 
dt.data.2[is.na(vy),vy:=0L] # Replace NA with 0 
dt.data.2[order(y.bin,x.bin)] # Display the final data.table output 

##  x.bin y.bin vx vy count 
## 1:  0  0 0 0  0 
## 2:  1  0 0 0  0 
## 3:  2  0 1 1  1 
## 4:  3  0 0 0  0 
## 5:  0  1 0 0  0 
## 6:  1  1 0 -2  3 
## 7:  2  1 0 0  0 
## 8:  3  1 0 0  0 
## 9:  0  2 0 0  1 
## 10:  1  2 0 0  0 
## 11:  2  2 0 2  3 
## 12:  3  2 -1 1  1 
## 13:  0  3 0 0  0 
## 14:  1  3 0 0  0 
## 15:  2  3 0 0  0 
## 16:  3  3 1 -1  1