【问题标题】:Reduce a data frame to fewer rows将数据框减少到更少的行
【发布时间】:2015-03-27 00:02:31
【问题描述】:

假设我有一个数据框“dat”,例如:

 col1     col2
  12       a
  43       a
  54       a
  11       a
  33       b
  43       b
  34       c
  34       c
  342      c
  343      c

现在我有一个向量

vec <- c(a,a,a,b,c,c)

我想要做的是根据向量“vec”删除数据框“dat”中的额外行,这意味着在数据框中只保留与“a”对应的前 3 行,保留仅前 1 行对应于“b”,仅保留 前 2 行对应于 c。

我应该得到输出为

 col1     col2
  12       a
  43       a
  54       a
  33       b
  34       c
  34       c

不用for循环最快的方法是什么?

【问题讨论】:

  • 如果您在每个字母类别中创建一个 seq_along 值,'merge' 将起作用。

标签: r dataframe reshape2


【解决方案1】:

这是一种使用splitMap的方式:

数据

dat <- read.table(header=T, text=' col1     col2
  12       a
  43       a
  54       a
  11       a
  33       b
  43       b
  34       c
  34       c
  342      c
  343      c',stringsAsFactors=F)

vec <-  c('a','a','a','b','c','c')

解决方案

#count frequencies
tabvec <- table(vec)

data.frame(do.call(rbind,
   #use split to split data.frame according to col2
   #use head to only choose the first n rows according to tabvec
   #convert output into a data.frame
   Map(function(x,y) head(x,y),  split(dat, as.factor(dat$col2)), tabvec)
))

输出:

    col1 col2
a.1   12    a
a.2   43    a
a.3   54    a
b     33    b
c.7   34    c
c.8   34    c

【讨论】:

    【解决方案2】:

    使用dplyr 你可以这样做:

    #create a data frame with frequencies
    tv <- data.frame(table(vec))
    
    #filter values       
    group_by(dat, col2) %>%
    filter(row_number() <= tv$Freq[tv$vec %in% col2])
    

    这给出了:

    #Source: local data frame [6 x 2]
    #Groups: col2
    #
    #  col1 col2
    #1   12    a
    #2   43    a
    #3   54    a
    #4   33    b
    #5   34    c
    #6   34    c
    

    【讨论】:

      【解决方案3】:

      这也可以在创建序列列之后完成

      library(data.table)
      setkey(setDT(dat)[, N:= 1:.N, col2], col2, N)
      dat[setDT(list(col2=vec))[, N:=1:.N, col2]][, N:= NULL][]
      #   col1 col2
      #1:   12    a
      #2:   43    a
      #3:   54    a
      #4:   33    b
      #5:   34    c
      #6:   34    c
      

      【讨论】:

      • 不错。我试图找出一个 DT 答案一段时间
      【解决方案4】:

      这是另一个Map() 方法。

      fvec <- factor(vec)
      ## find the index for the first occurrence of a new level
      m <- match(levels(fvec), df$col2)
      
      df[unlist(Map(seq, from = m, length.out = tabulate(fvec))), ]
      #   col1 col2
      # 1   12    a
      # 2   43    a
      # 3   54    a
      # 5   33    b
      # 7   34    c
      # 8   34    c
      

      或者你可以在匹配后使用rle()

      rl <- rle(match(vec, df$col2))
      df[unlist(Map(seq, rl$values, length.out = rl$lengths)),]
      #   col1 col2
      # 1   12    a
      # 2   43    a
      # 3   54    a
      # 5   33    b
      # 7   34    c
      # 8   34    c
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-02-01
        • 1970-01-01
        • 2018-09-11
        • 1970-01-01
        • 2021-10-06
        • 2018-05-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多