代码之家  ›  专栏  ›  技术社区  ›  Laura

合并数据帧仅拾取跨数据帧共享相同名称开头的列

  •  2
  • Laura  · 技术社区  · 6 年前

    我想用这两个数据帧来创建另一个:

    df<-as.data.frame(matrix(rexp(200, rate=.1), ncol=10))
    colnames(df)<-c("one","two","three","four","five","six","seven","eight","nine","ten")
    df
    
    
        df.new<-as.data.frame(matrix(rexp(155, rate=.1), ncol=8))
    colnames(df.new)<-c("one.two","one.two.new","three.two","three.two.new","five.one","five.one.new","seven.two","seven.two.new")
    df.new
    

    我的想法是用这些列创建一个数据帧:

    (one|one.two|one.two.new|three|three.two|three.two.new|five|five.one|five.one.new)
    

    我可以手动操作,但我的数据帧比这些要大得多。

    有没有可能用dplyr包来实现这一点??

    2 回复  |  直到 6 年前
        1
  •  1
  •   mlt    6 年前

    这是另一个较短的选择。我只是不喜欢宽大的桌子…所以你总有一天会把它融化的。

    to.pick <- unique(unlist(sapply(colnames(df.new), function(x) {
      Reduce(function(a,b) paste(a, b, sep="."), strsplit(x, '.', fixed=TRUE)[[1]], accumulate=TRUE)
    })))
    zz <- cbind(df, df.new)
    out <- subset(zz, select=to.pick)
    colnames(out)
     [1] "one"           "one.two"       "one.two.new"   "three"         "three.two"     "three.two.new" "five"         
     [8] "five.one"      "five.one.new"  "seven"         "seven.two"     "seven.two.new"
    

    原始答案

    对于按列名部分过滤的数据,使用熔化/铸造。

    library(tidyr)
    

    df$idx <- 1:nrow(df)
    gdf <- gather(df, key, value, -idx)
    df.new$idx <- 1:nrow(df.new)
    gdf.new <- gather(df.new, key, value, -idx)
    

    获得独特的第一部分

    uu <- unique(gdf.new$key)
    to.pick <- sapply(uu, function(x) {
      strsplit(x, '.', fixed=TRUE)[[1]][1]
      })
    

    gdf.ss <- subset(gdf, key %in% to.pick)
    

    仍然以“正常”长格式合并数据。

    out <- rbind(gdf.ss, gdf.new)
    

    抛弃成“丑陋”的宽格式

    out.wide <- spread(out, key, value)
    colnames(out.wide)
     [1] "idx"           "five"          "five.one"     
     [4] "five.one.new"  "one"           "one.two"      
     [7] "one.two.new"   "seven"         "seven.two"    
    [10] "seven.two.new" "three"         "three.two"    
    [13] "three.two.new"
    

    如果你坚持不严格按字母顺序排列,我会更新我的答案。

        2
  •  0
  •   rgt47    6 年前

    列以三个为一组,让N=为组数。

     N=3 # for the example provided
     foo=seq(1,2*N+1,2) 
     dplyr::bind_cols(df, df.new) %>% dplyr::select(names(.)[c(foo, 
     foo+10, foo+11)])