2011-06-09 56 views
1

是否有会,让来自DF这样说子集大数据帧

vec <- data.frame(Names = c("var1","var2","var3","var4","var5","var6","var7", 
          "var8","var9","var10","var11","var12","var13", 
          "var14") , 
        phase1= runif(14), 
        phase1.away= runif(14), 
        phase1_in= runif(14), 
        phase1_out= runif(14), 
        phase1.1= runif(14), 
        phase1.away.1= runif(14), 
        phase1_in.1= runif(14), 
        phase1_out.1= runif(14), 
        phase1.2= runif(14), 
        phase1.away.2= runif(14), 
        phase1_in.2= runif(14), 
        phase1_out.2= runif(14)) 

赋予了新的DF因为这样一个快速和巧妙的方法:

-allways根据phase1.x订购,给与值相对应的变量的名称phase1_in和phase1_out值,但不包含phase1.away。

我在做什么是根本

vec.o<-vec[with(vec, order(-phase1)),] 
d1<-vec.o[c("Names","phase1","phase1_in","phase1_out")] 

vec.o<-vec[with(vec, order(-phase1.1)),] 
d2<-vec.o[c("Names","phase1.1","phase1_in.1","phase1_out.1")] 

cbind(d1,d2) 

这是非常枯燥,我也相信反R-ISH。任何聪明的想法?我正在处理大数据帧永久和R似乎 有点麻烦。有没有什么好的文献可以推荐用于这些目的? (负载许多变量,创建名字对他们来说,操作这些变量等...)

回答

3

编辑:为案件phase.x修正去10及更高版本。

我相信你有相当多的比phase1.1,phase1.2多,所以使用正则表达式一般的解决办法是沿着线的东西:

# Make an id vector for the phase1.x, and give Names id -1 
# gives a warning as character is transformed to NA 
id <- as.numeric(gsub(".*\\.(\\d+$)","\\1",names(vec))) 
id[1] <- -1 
id[is.na(id)] <- 0 # first occurence, no .x 


veclist <- lapply(unique(id)[-1],function(i){ 
    #select all variables necessary, exclude the away 
    out <- vec[id %in% c(i,-1) & !grepl("away",names(vec))] 
    # find the phase1.x for ordering 
    ovec <- grepl("phase1(\\.\\d+)?$",names(out)) 
    # order and produce 
    out[order(out[,ovec]),] 
}) 

do.call(cbind,veclist) 

它的基础是承认的最后一个以点开头的数字,并将其切除。如果没有最后一个数字前面有一个点,它可能是Names变量(我用-1表示)或第一个阶段(我用0表示)。

现在你有一个id向量,可以很容易地选择属于一起的变量,所以你可以遍历id的唯一值,除了第一个(为-1)。再次使用正则表达式,您可以获得想要构建新数据框的任何变量。最后的do.call再次组合了所有这些数据帧。

顺便说一下,排序子数据框比先排序原始数据框然后选择变量要快得多。这是你在解决nullglob方面的收获。

+0

不错,尽管看起来phase.x的阶段是阶段10或更高阶段,但ID会产生零点 – Alex 2011-06-09 12:25:24

+0

@Alex:很好的捕获。我纠正包括phase.x高于10。 – 2011-06-09 12:48:55

1

这不是特别聪明,但它是超过两倍的速度(根据我的简单的基准):

o1 <- order(-vec$phase1) 
o2 <- order(-vec$phase1.1) 
cbind(vec[o1,c("Names","phase1","phase1_in","phase1_out")], 
     vec[o2,c("Names","phase1.1","phase1_in.1","phase1_out.1")]) 

基准是在这里:

> n <- 2e5 
> vec<-data.frame(Names = as.character(runif(n)) , 
+     phase1= runif(n), 
+     phase1.away= runif(n), 
+     phase1_in= runif(n), 
+     phase1_out= runif(n), 
+     phase1.1= runif(n), 
+     phase1.away.1= runif(n), 
+     phase1_in.1= runif(n), 
+     phase1_out.1= runif(n), 
+     phase1.2= runif(n), 
+     phase1.away.2= runif(n), 
+     phase1_in.2= runif(n), 
+     phase1_out.2= runif(n)) 
> 
> 
> test1 <- function(){ 
+ vec.o<-vec[with(vec, order(-phase1)),] 
+ d1<-vec.o[c("Names","phase1","phase1_in","phase1_out")] 
+ vec.o<-vec[with(vec, order(-phase1.1)),] 
+ d2<-vec.o[c("Names","phase1.1","phase1_in.1","phase1_out.1")] 
+ d3 <- cbind(d1,d2) 
+ } 
> system.time(test1()) 
    user system elapsed 
    1.764 0.048 1.811 
> 
> 
> test2 <- function(){ 
+ o1 <- order(-vec$phase1) 
+ o2 <- order(-vec$phase1.1) 
+ d4 <- cbind(vec[o1,c("Names","phase1","phase1_in","phase1_out")], 
+    vec[o2,c("Names","phase1.1","phase1_in.1","phase1_out.1")]) 
+ } 
> system.time(test2()) 
    user system elapsed 
    0.736 0.056 0.791 
+0

谢谢,但我有260个阶段的数据框,这是什么使我最感兴趣,因为我想避免手动输入 – Alex 2011-06-09 11:55:23

+0

您不需要使用列名来选择列;你可以使用列索引,这可能会更快,更容易输入。 – nullglob 2011-06-09 12:24:40