对于每一行,按最高值对列名进行排序

时间:2018-11-05 13:57:28

标签: r sorting if-statement

我有一个看起来像这样的数据框。

df <- data.frame(name = c("bob", "john", "peter", "chris"),
    a = c(0, 0, 0, 0), b = c(2, 2, 1, 0), c = c(4, 0, 0, 1), d = c(0, 2, 1, 0), e = c(1, 0, 5, 0))
df

   name a b c d e
1   bob 0 2 4 0 1
2  john 0 2 0 2 0
3 peter 0 1 0 1 5
4 chris 0 0 1 0 0

对于每一行,我需要找到按值排序的列,如以下示例所示:

   name output
1   bob  c,b,e
2  john    b,d
3 peter  e,b,d
4 chris      c

我不知道该怎么做。

2 个答案:

答案 0 :(得分:4)

您可以这样做:

df <- data.frame(name = c("bob", "john", "peter", "chris"),
                 a = c(0, 0, 0, 0), b = c(2, 2, 1, 0), c = c(4, 0, 0, 1), d = c(0, 2, 1, 0), e = c(1, 0, 5, 0))
sortRowNames <- function(x) { x <- x[x!=0]; y <- sort(x, decr=TRUE); paste0(names(y), collapse=',') }
df$new <- apply(df[-1], 1, sortRowNames)
df
# > df
#    name a b c d e   new
# 1   bob 0 2 4 0 1 c,b,e
# 2  john 0 2 0 2 0   b,d
# 3 peter 0 1 0 1 5 e,b,d
# 4 chris 0 0 1 0 0     c

以下是该函数的简短版本:

sortRow2 <- function(x) paste0(names(sort(x[x!=0], decr=TRUE)), collapse=',')

答案 1 :(得分:1)

这是gather / spread通过tidyverse完成的方式,

library(tidyverse)

df %>% 
 gather(var, val, -name) %>% 
 group_by(name) %>% 
 arrange(-val) %>% 
 mutate(output = toString(var[val != 0])) %>% 
 spread(var, val) %>% 
 select(name, output)

给出,

# A tibble: 4 x 2
# Groups:   name [4]
  name  output 
  <chr> <chr>  
1 bob   c, b, e
2 chris c      
3 john  b, d   
4 peter e, b, d