【问题标题】:Subsetting large data frames子集大数据框
【发布时间】:2011-06-09 11:24:22
【问题描述】:

有没有一种快速而聪明的方法,比如说像这样的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:

-总是根据 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 似乎是 有点麻烦。有没有什么好的文献可以推荐用于这些目的? (加载许多变量,为它们创建名称,对这些变量进行操作等......,)

【问题讨论】:

    标签: r dataframe


    【解决方案1】:

    编辑:针对情况进行了更正,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 解决方案中的收获。

    【讨论】:

    • 很好,虽然看起来 phase.x 的名称是 phase.10 或更高,ID 产生零
    • @Alex :不错的收获。我更正了包含 phase.x 高于 10。
    【解决方案2】:

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

    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
    

    【讨论】:

    • 谢谢,但我有 260 个阶段的数据框,这是我最关心的,因为我想避免手动输入
    • 您不需要使用列名来选择列;您可以改用列索引,这可能会更快、更容易输入。
    猜你喜欢
    • 2020-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-31
    • 1970-01-01
    • 1970-01-01
    • 2019-02-04
    相关资源
    最近更新 更多