Я хочу создать переменную, которая берет свое значение из 5 двоичных (Y/N) столбцов, чтобы каждое «ДА» считалось как 1, а каждое «НЕТ» как 0, поэтому каждое наблюдение будет иметь значение для этой новой переменной между 0 и 5.
В настоящее время я думаю об этом, чтобы создать новую переменную со всеми значениями в 0 и запустить что-то вроде этого для каждой из определяющих переменных:
new_variable <- if (variable_x == "YES"){increment(new_variable)}
но это кажется немного неэлегантным. Кто-нибудь знает, есть ли лучший способ сделать это?
R разработан так, что каждый TRUE
уже является 1
, а каждый FALSE
уже является 0
. Итак, если вы хотите добавить, сколько TRUE
в c(TRUE, FALSE, TRUE)
, вы можете просто суммировать это:
sum(c(TRUE, FALSE, TRUE))
Так что в большинстве случаев вам действительно не нужно ничего настраивать. Если вы действительно, очень хотели это сделать, as.numeric
сделает свою работу:
as.numeric(c(TRUE, FALSE, TRUE)
Выгодно кодировать двоичные значения как логические. В вашем случае вы можете сделать это на лету, используя ==
как в
sum(c("YES", "NO", "YES", "YES", "NO") == "YES")
Если в ваших данных есть какие-либо NA
, вам придется принять решение и, вероятно, вы захотите использовать аргумент sum
s na.rm
.
sum(c("YES", "YES", NA, "NO", "NO", NA) == "YES", na.rm = TRUE)
Насколько я понимаю ваш вопрос, вы можете использовать rowSums
вместо sum
.
Думаю этого должно хватить...
library(tidyverse)
# creating dataframe
df = data.frame(col1 = sample(c("YES","NO"),10,replace = T),
col2 = sample(c("YES","NO"),10,replace = T),
col3 = sample(c("YES","NO"),10,replace = T),
col4 = sample(c("YES","NO"),10,replace = T),
col5 = sample(c("YES","NO"),10,replace = T))
apply(df,2,function(x) as.numeric(x == "YES")) %>% # converting YES/NO to binary
as.data.frame() %>% # changing from matrix to dataframe
mutate(sum = rowSums(across(where(is.numeric)), na.rm = T)) # creating sum
#> col1 col2 col3 col4 col5 sum
#> 1 1 0 0 1 0 2
#> 2 1 0 1 1 1 4
#> 3 0 0 0 0 1 1
#> 4 1 1 0 1 0 3
#> 5 0 0 1 0 0 1
#> 6 0 0 0 0 1 1
#> 7 0 1 0 1 0 2
#> 8 1 0 1 0 0 2
#> 9 1 1 0 1 0 3
#> 10 1 1 1 0 0 3
Вы также можете использовать rowSums()
непосредственно в операторе dplyr
.
library(dplyr)
df %>%
mutate(x = rowSums(across(all_of(c("col1", "col2", "col3", "col4", "col5")), `==`, "YES")))
# something col1 col2 col3 col4 col5 x
# 1 0.113703411 NO NO YES NO NO 1
# 2 0.622299405 NO NO NO YES NO 1
# 3 0.609274733 NO NO YES NO NO 1
# 4 0.623379442 YES NO YES NO NO 2
# 5 0.860915384 NO NO YES NO YES 2
# 6 0.640310605 NO NO NO YES NO 1
# 7 0.009495756 NO YES YES YES YES 4
# 8 0.232550506 YES NO NO YES YES 3
# 9 0.666083758 NO NO NO YES NO 1
# 10 0.514251141 NO NO YES NO YES 2
Вы также можете использовать помощники tidyselect в зависимости от того, как настроен ваш фрейм данных.
df %>%
mutate(x = rowSums(across(starts_with("col"), `==`, "YES")))
df %>%
mutate(x = rowSums(across(col1:col5, `==`, "YES")))
По поводу использования na.rm = TRUE
. Я бы не стал этого делать. То, как обращаться с АН, требует более тщательного обдумывания. Не следует просто предполагать, что NA равно «НЕТ», не зная лучше вашей проблемы. Если это «НЕТ», то вместо этого я бы заменил это значение на каком-то этапе рабочего процесса.
Данные:
set.seed(1234)
df <- data.frame(something = runif (10),
col1 = sample(c("YES","NO"),10,replace = T),
col2 = sample(c("YES","NO"),10,replace = T),
col3 = sample(c("YES","NO"),10,replace = T),
col4 = sample(c("YES","NO"),10,replace = T),
col5 = sample(c("YES","NO"),10,replace = T))
Или прямо это
df %>% mutate(sum = rowSums(across(1:5, ~ .x == "YES"), na.rm = T))