检查条件并返回满足条件的列的名称

时间:2018-05-14 08:50:26

标签: r filter dplyr mutate

我有一个 dataframe ,如下所示:

df_start <- data.frame(
  a = c(1, 1, 1, 1, 1), 
  b = c(0, 1, 0, 0, 0), 
  c = c(1, 0, 0, 0, 0), 
  n = c(0, 0, 0, 1, 0))

我想测试条件,如果来自df_start[,2:n]的任何列(其中n显示数据帧的最后一列)等于df$a,那么创建两个新列,其中第一列如果条件为TRUE则返回1,如果不是则返回0,另一个给出条件为TRUE的列的名称。

我设法创建了第一列:

library(dplyr)

# check condition
df_start <- df_start %>% mutate(cond = ifelse(a == b | a == c | a == n, 1, 0))

即使我认为我需要一种不同的方法,因为每次都可能有不同的列数。所以我需要测试列a的条件以及从2到最后一列的所有列,但我还需要知道条件满足哪一列。

期望的输出:

# desired output
df_end <- data.frame(a = c(1, 1, 1, 1, 1), 
                     b = c(0, 1, 0, 0, 0), 
                     c = c(1, 0, 0, 0, 0), 
                     n = c(0, 0, 0, 1, 0),
                     cond = c(1,1,0,1,0),
                     col_name = c("c", "b", NA, "n", NA))

有没有办法用dplyr或基础R来做到这一点?虽然任何其他解决方案都很受欢

4 个答案:

答案 0 :(得分:2)

另一个基础R解决方案:

m <- df_start[,1] == df_start[,2:4]

df_start$cond <- rowSums(m)
df_start$col_name[!!rowSums(m)] <- names(df_start[2:4])[max.col(m) * rowSums(m)]

给出:

> df_start
  a b c n cond col_name
1 1 0 1 0    1        c
2 1 1 0 0    1        b
3 1 0 0 0    0     <NA>
4 1 0 0 1    1        n
5 1 0 0 0    0     <NA>

答案 1 :(得分:1)

以下仅使用基础R. 请注意,要创建列JAVA_OPTS,不需要cond

ifelse

答案 2 :(得分:1)

您可以尝试tidyverse。我喜欢将gatherspread用于此类方法。

library(tidyverse)
df_start %>% 
  rownames_to_column() %>% 
  gather(k, v, -a, -rowname) %>% 
  group_by(rowname) %>% 
  mutate(cond=ifelse(any(a==v), 1, 0)) %>% 
  mutate(col_name=ifelse(cond==1, k[v==1], NA)) %>% 
  ungroup() %>% 
  spread(k, v) %>% 
  select(-rowname)
# A tibble: 5 x 6
      a  cond col_name     b     c     n
  <dbl> <dbl> <chr>    <dbl> <dbl> <dbl>
1     1     1 c            0     1     0
2     1     1 b            1     0     0
3     1     0 NA           0     0     0
4     1     1 n            0     0     1
5     1     0 NA           0     0     0

或者不转换像

这样的管道/应用解决方案
df_start %>% 
  mutate(col_name=apply(.[-1], 1, function(x, y) y[x==1], colnames(.)[-1])) %>% 
  mutate(cond=as.numeric(apply(.[-ncol(.)], 1, function(x) any(x[1] == x[-1]))))
  a b c n col_name cond
1 1 0 1 0        c    1
2 1 1 0 0        b    1
3 1 0 0 0             0
4 1 0 0 1        n    1
5 1 0 0 0             0

答案 3 :(得分:0)

很好的解决方案@Jimbou与tidyverse。完成后,您可以通过更改Jimbous代码中的最后一行来安排结果:

select(-c(rowname, cond, col_name), c(cond, col_name))