Проверьте условие и верните имя столбца, для которого выполняется условие - PullRequest
0 голосов
/ 14 мая 2018

У меня есть фрейм данных , который выглядит следующим образом:

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, затем создайте два новых столбца, из которых первый возвращает 1, если условие имеет значение ИСТИНА, и 0, если это не так, а другой дает имя столбца, для которого условие было ИСТИНА.

Мне удалось создать первый столбец следующим образом:

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 голосов
/ 14 мая 2018

Отличное решение @ Jimbou с Tidyverse.Для завершения вы можете упорядочить результат, изменив последнюю строку в коде Jimbous:

select(-c(rowname, cond, col_name), c(cond, col_name))
0 голосов
/ 14 мая 2018

Вы можете попробовать tidyverse.Мне нравится использовать gather и spread для таких подходов.

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
0 голосов
/ 14 мая 2018

Другое базовое решение 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>
0 голосов
/ 14 мая 2018

В следующем примере используется только база R.
Обратите внимание, что для создания столбца cond нет необходимости в ifelse.

df_end <- df_start
df_end$cond <- with(df_start, as.integer(a == b | a == c | a == n))
df_end$col_name <- NA
inx <- apply(df_start[-1] == df_start[[1]], 1, function(x) min(which(x)) + 1)
is.na(inx) <- is.infinite(inx)
df_end$col_name <- names(df_start)[inx]

df_end
#  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>
.
...