在R中创建列包含前n个最高行

时间:2014-12-13 10:04:30

标签: r dataframe

我的数据集如下所示:

    group <- c(1,2,3,4,5,6,7)
    item1.sep <- sample(1:10,7)
    item2.sep <- sample(1:10,7)
    item3.sep<- sample(1:10,7)
    item4.sep<- sample(1:10,7)
    item5.sep<- sample(1:10,7)
    item1.oct<- sample(1:10,7)
    item2.oct <- sample(1:10,7)
    item3.oct<- sample(1:10,7)
    item4.oct<- sample(1:10,7)
    item5.oct<- sample(1:10,7)

df <- data.frame(group,item1.sep,item2.sep,item3.sep,item4.sep,item5.sep,
                 item1.oct,item2.oct,item3.oct,item4.oct,item5.oct)


    group   item1.sep   item2.sep....   item5.oct
       1       9           9             4  
       2       4           4             7  
       3       7           7             2  
       4       3           8             5  
       5       8           3             1  
       6       6          10             8  
       7      10           2             6  

我想创建2个新列,每个月包含前2项作为字符。也许max和merge的组合对这个有帮助

          Top2_Sept   Top2_Oct             group....    item5.oct
 item3.sep,item2.sep  item5.Oct,item2.Oct      1         9  
 item4.sep,item1.sep       .                   2         4          
 item2.sep,item5.sep       .                   .         .
 item4.sep,item2.sep       .                   .         .
 item1.sep,item3.sep       .                   .         .
 item2.sep,item5.sep       .                   .         .
 item4.sep,item1.sep       .                   .         

2 个答案:

答案 0 :(得分:2)

这是一个data.table解决方案。

library(data.table)
DT <- as.data.table(df)
DT[,Top2_Sept:=paste(names(.SD)[order(unlist(.SD),decreasing=TRUE)[1:2]],collapse=","),
          .SDcols=2:6,by=group]
DT[,Top2_Oct:=paste(names(.SD)[order(unlist(.SD),decreasing=TRUE)[1:2]],collapse=","),
          .SDcols=7:11,by=group]
DT[,list(group,Top2_Sept,Top2_Oct)]
#    group           Top2_Sept            Top2_Oct
# 1:     1 item5.sep,item3.sep item2.oct,item1.oct
# 2:     2 item2.sep,item4.sep item1.oct,item5.oct
# 3:     3 item5.sep,item3.sep item3.oct,item2.oct
# 4:     4 item4.sep,item1.sep item5.oct,item1.oct
# 5:     5 item2.sep,item4.sep item4.oct,item5.oct
# 6:     6 item1.sep,item2.sep item1.oct,item2.oct
# 7:     7 item1.sep,item2.sep item1.oct,item2.oct

您的示例不太可重现,因为您在创建随机样本之前没有set.seed(...)。如果您在开始时set.seed(1),则上述结果将重现。

此外,您的规则存在歧义。假设给定行的item1.sep:item5.sep(8,7,7,6,5)。然后顶部项目在第一个col中,但第二个项目可以在第二个或第三个列中。你没有提出解决这个问题的规则。

答案 1 :(得分:1)

尝试

lst1 <- split(colnames(df)[-1],sub(".*\\.", '',colnames(df)[-1]))
df[paste("Top2", c("Oct", "Sept"), sep="_")] <-  lapply(lst1, function(x) {
            nm1 <- colnames(df[x])
           apply(df[x], 1, function(.x) 
           toString(nm1[order(.x, decreasing=TRUE)[1:2]]))})

或者

lst1 <- lapply(month.abb[9:10], function(x)
         df[grep(x, colnames(df), ignore.case=TRUE)])
nm1 <- lapply(lst1, colnames)
f1 <- function(x,y) apply(x, 1, function(.x)
          toString(y[order(.x, decreasing=TRUE)[1:2]]))

 df[paste('Top2', month.abb[9:10], sep="_")] <- Map(f1, lst1, nm1)
相关问题