R сравнить значения столбцов по строкам - PullRequest
1 голос
/ 11 июля 2020

У меня есть фрейм данных со структурой ниже, и я хотел бы создать дополнительный столбец, который сравнивает все значения столбцов по строкам на основе определенных критериев, то есть M == 1 и всех других столбцов == 0

как я могу написать код, используя dplyr или иным образом, чтобы выполнить этот тип операции построчно в большом наборе данных?

      M     B     L     H
  <dbl> <dbl> <dbl> <dbl>
1     1     0     0     0
2     0     1     0     0
3     1     0     0     0
4     0     1     0     0
5     0     0     1     0
6     0     0     0     1

1 Ответ

0 голосов
/ 11 июля 2020

Вот один из вариантов с map/reduce в остальных столбцах, чтобы проверить, все ли они равны 0, а затем выполнить & с M == 1

library(dplyr)# 1.0.0
library(purrr)
df1 %>%
     mutate(flag = M == 1 & select(., -M) %>% 
                              map(., `==`, 0) %>%
                              reduce(`&`))
#  M B L H  flag
#1 1 0 0 0  TRUE
#2 0 1 0 0 FALSE
#3 1 0 0 0  TRUE
#4 0 1 0 0 FALSE
#5 0 0 1 0 FALSE
#6 0 0 0 1 FALSE

Другой вариант - rowwise с c_across (из dplyr >= 1.0) (но он мог быть медленнее)

df1 %>%
    rowwise %>% 
    mutate(new = all(c_across(B:H) == 0) & M == 1)
# A tibble: 6 x 5
# Rowwise: 
#      M     B     L     H new  
#  <int> <int> <int> <int> <lgl>
#1     1     0     0     0 TRUE 
#2     0     1     0     0 FALSE
#3     1     0     0     0 TRUE 
#4     0     1     0     0 FALSE
#5     0     0     1     0 FALSE
#6     0     0     0     1 FALSE

Параметр map/reduce аналогичен параметру base R с lapply/Reduce, где мы l oop по столбцам набора данных с помощью lapply (здесь df1[-1], поскольку мы не хотим использовать первый столбец, т.е. 'M'), создайте list логических vector s с ==,

lapply(df1[-1], `==`, 0)
#$B
#[1]  TRUE FALSE  TRUE FALSE  TRUE  TRUE

#$L
#[1]  TRUE  TRUE  TRUE  TRUE FALSE  TRUE

#$H
#[1]  TRUE  TRUE  TRUE  TRUE  TRUE FALSE

, затем Reduce list с одним логическим вектором с &, сравнив соответствующие позиции элементов list, т.е. если все они равны TRUE, он возвращает ИСТИНА

Reduce(`&`, lapply(df1[-1], `==`, 0))
#[1]  TRUE FALSE  TRUE FALSE FALSE FALSE

, а затем добавляет M == 0

df1$M == 0 & Reduce(`&`, lapply(df1[-1], `==`, 0))

Или другой вариант в base R: rowSums

df1$M == 1 & !rowSums(df1[-1] != 0)

Или также может быть записан как

df1$M == 1 & rowSums(df1[-1] == 0) == ncol(df1[-1])

data

df1 <- structure(list(M = c(1L, 0L, 1L, 0L, 0L, 0L), B = c(0L, 1L, 0L, 
1L, 0L, 0L), L = c(0L, 0L, 0L, 0L, 1L, 0L), H = c(0L, 0L, 0L, 
0L, 0L, 1L)), class = "data.frame", row.names = c("1", "2", "3", 
"4", "5", "6"))
...