【问题标题】:Efficient way to aggregate data based on two criteria in R基于 R 中的两个标准聚合数据的有效方法
【发布时间】:2018-01-23 15:14:22
【问题描述】:

我从大型数据框中抽取了一个样本。对于每个 id,我想要 每个类别前 n 个因素。我曾尝试使用嵌套的 for 循环,但我认为这根本不是有效的方法。请在下面找到数据和我的尝试。

id = c(1,1,1,1,1,1,2,2,2,2,2,2,2) 
category = c("A","A","A","B","B","B","A","A","A","A","B","B","B") 
factor= c("A1","A2","A3","B1","B2","B3","A2","A1","A3","A4","B2","B1","B3") 
rank = c(2,1,5,2,1,6,12,10,8,9,23,12,10) 

df = data.frame(id,category,factor,rank)

df$rank <- as.integer(df$rank)
cat <- as.data.frame(table(df$category))
list1 <- list()
list2 <- list()

for(i in 1:length(unique(df$id))){

  for(j in 1:nrow(cat))
  {
    list1[[j]] <- df[order(rank),][id==df[,id[i]]&category==cat[[1]][j] ,][1:2] 
  }
  rbind_list1 <- rbindlist(list1)
  list2[[i]] <- rbind_list1[rowSums(is.na(rbind_list1)) != ncol(rbind_list1),]

}
final <- do.call(rbind, list2)
df <- final[rowSums(is.na(final)) != ncol(final),]



DESIRED OUTPUT:

id  category factor rank
1     A        A2    1
1     A        A1    2
1     B        B1    2
1     B        B2    1
2     A        A3    8
2     A        A4    9
2     B        B3    10
2     B        B1    12

【问题讨论】:

    标签: r dataframe dplyr data.table tidyr


    【解决方案1】:

    使用基础 R,您可以这样做:

    topn <- function(df, n) do.call(rbind, by(df, list(id, category), function(x) x[order(x$rank), ][1:n, ]))
    
    topn(df, 2)  
    
       id category factor rank
    2   1        A     A2    1
    1   1        A     A1    2
    9   2        A     A3    8
    10  2        A     A4    9
    5   1        B     B2    1
    4   1        B     B1    2
    13  2        B     B3   10
    12  2        B     B1   12
    

    【讨论】:

      【解决方案2】:

      使用 data.table 你就可以做到

      library(data.table)
      n <- 2
      df <- setDT(df)
      df[order(rank),.SD[1:n], by = .(id,category)]
      
      1:  1        A     A2    1
      2:  1        A     A1    2
      3:  1        B     B2    1
      4:  1        B     B1    2
      5:  2        A     A3    8
      6:  2        A     A4    9
      7:  2        B     B3   10
      8:  2        B     B1   12
      

      或者如果你想更快

      df[df[order(rank),.I[1:n], by = .(id,category)]$V1]
      

      我不明白 dplyr,让别人找到它

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-17
        • 2018-12-16
        • 2018-12-11
        相关资源
        最近更新 更多