Я хочу создать новый столбец «X11», который суммирует все единицы условно в зависимости от того, сколько NA имеется в выбранном количестве столбцов. В данном случае я рассматриваю 4 переменные: X1, X2, X3 и X4.
Пример: если есть 1 NA, то я хочу посмотреть на оставшиеся 3 переменные, которые имеют значения, и посчитать, сколько там единиц. Если есть 2 NA, то я хочу посмотреть на оставшиеся 2 переменные и посчитать, сколько там единиц. Если у меня есть 3 NA, то я хочу посмотреть на оставшуюся 1 переменную и определить, равна ли она 1. Если у меня есть все 4 NA, то это даст мне 0.
У меня есть эти данные:
df <- data.frame(replicate(10,sample(0:2, 10, rep=TRUE)))
df <- replace(df, df == 0, NA)
Мой фрейм данных выглядит так:
X1 X2 X3 X4 X5 X6 X7 X8 X9 X10
1 1 1 NA 1 NA NA NA 1 1 2
2 NA 1 1 NA 2 NA 2 2 NA 1
3 1 NA 1 1 NA NA 1 2 NA 1
4 2 2 2 1 1 2 1 NA 2 2
5 NA 2 NA 2 NA 2 1 NA 1 1
6 2 2 1 1 2 NA 1 2 1 1
7 1 2 NA NA 2 1 1 NA NA 1
8 2 2 NA NA 1 NA NA 2 NA 1
9 1 NA 1 2 2 1 2 NA NA 1
10 NA 2 1 NA NA NA NA 2 2 NA
Я хочу, чтобы мой результат выглядел так:
X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11
1 1 1 NA 1 NA NA NA 1 1 2 3
2 NA 1 1 NA 2 NA 2 2 NA 1 2
3 1 NA 1 1 NA NA 1 2 NA 1 3
4 2 2 2 1 1 2 1 NA 2 2 1
5 NA 2 NA 2 NA 2 1 NA 1 1 0
6 2 2 1 1 2 NA 1 2 1 1 2
7 1 2 NA NA 2 1 1 NA NA 1 1
8 2 2 NA NA 1 NA NA 2 NA 1 0
9 1 NA 1 2 2 1 2 NA NA 1 2
10 NA 2 1 NA NA NA NA 2 2 NA 1
Вот пример моего текущего кода:
vars <- c("X1", "X2", "X3", "X4")
df <- df %>%
mutate(missing_vars = rowSums(across(vars, ~is.na(.))),
nonmissing_vars = 7-vars)
df <- df %>%
mutate(zero_na = case_when(missing_vars == 0 & (X1 == 2 & X2 == 2 & X3 == 2 & X4 == 2) ~ 1,
(missing_vars == 0 & (X1 == 1 & X2 == 2 & X3 == 2 & X4 == 2) |
(X1 == 2 & X2 == 1 & X3 == 2 & X4 == 2) |
(X1 == 2 & X2 == 2 & X3 == 1 & X4 == 2) |
(X1 == 2 & X2 == 2 & X3 == 2 & X4 == 1)) ~ 2,
(missing_vars == 0 & (X1 == 1 & X2 == 1 & X3 == 2 & X4 == 2) |
(X1 == 1 & X2 == 2 & X3 == 1 & X4 == 2) |
(X1 == 1 & X2 == 2 & X3 == 2 & X4 == 1) |
(X1 == 2 & X2 == 1 & X3 == 1 & X4 == 2) |
(X1 == 2 & X2 == 2 & X3 == 1 & X4 == 1) |
(X1 == 2 & X2 == 1 & X3 == 2 & X4 == 1)) ~ 3,
(missing_vars == 0 & (X1 == 1 & X2 == 1 & X3 == 1 & X4 == 2) |
(X1 == 1 & X2 == 1 & X3 == 2 & X4 == 1) |
(X1 == 1 & X2 == 2 & X3 == 1 & X4 == 1) |
(X1 == 2 & X2 == 1 & X3 == 1 & X4 == 1)) ~ 4,
missing_vars == 0 & (X1 == 1 & X2 == 1 & X3 == 1 & X4 == 1) ~ 5))
brfss <- brfss %>%
mutate(one_na = case_when(missing_vars == 1 & (is.na(X1) & X2 == 2 & X3 == 2 & X4 == 2) ~ 1,
missing_vars == 1 & (X1 == 2 & is.na(X2) & X3 == 2 & X4 == 2) ~ 1,
missing_vars == 1 & (X1 == 2 & X2 == 2 & is.na(X3) & X4 == 2) ~ 1,
missing_vars == 1 & (X1 == 2 & X2 == 2 & X3 == 2 & is.na(X4)) ~ 1,
missing_vars == 1 & (is.na(X1) & X2 == 1 & X3 == 2 & X4 == 2) ~ 2,
missing_vars == 1 & (X1 == 1 & is.na(X2) & X3 == 2 & X4 == 2) ~ 2,
missing_vars == 1 & (X1 == 1 & X2 == 2 & is.na(X3) & X4 == 2) ~ 2,
missing_vars == 1 & (X1 == 1 & X2 == 2 & X3 == 2 & is.na(X4)) ~ 2,
missing_vars == 1 & (is.na(X1) & X2 == 2 & X3 == 1 & X4 == 2) ~ 2,
missing_vars == 1 & (X1 == 2 & is.na(X2) & X3 == 1 & X4 == 2) ~ 2,
missing_vars == 1 & (X1 == 2 & X2 == 1 & is.na(X3) & X4 == 2) ~ 2,
missing_vars == 1 & (X1 == 2 & X2 == 1 & X3 == 2 & is.na(X4)) ~ 2,
missing_vars == 1 & (is.na(X1) & X2 == 2 & X3 == 2 & X4 == 1) ~ 2,
missing_vars == 1 & (X1 == 2 & is.na(X2) & X3 == 2 & X4 == 1) ~ 2,
missing_vars == 1 & (X1 == 2 & X2 == 2 & is.na(X3) & X4 == 1) ~ 2,
missing_vars == 1 & (X1 == 2 & X2 == 2 & X3 == 1 & is.na(X4)) ~ 2,
missing_vars == 1 & (is.na(X1) & X2 == 1 & X3 == 1 & X4 == 2) ~ 3,
missing_vars == 1 & (X1 == 1 & is.na(X2) & X3 == 1 & X4 == 2) ~ 3,
missing_vars == 1 & (X1 == 1 & X2 == 1 & is.na(X3) & X4 == 2) ~ 3,
missing_vars == 1 & (X1 == 1 & X2 == 1 & X3 == 2 & is.na(X4)) ~ 3,
missing_vars == 1 & (is.na(X1) & X2 == 2 & X3 == 1 & X4 == 1) ~ 3,
missing_vars == 1 & (X1 == 2 & is.na(X2) & X3 == 1 & X4 == 1) ~ 3,
missing_vars == 1 & (X1 == 2 & X2 == 1 & is.na(X3) & X4 == 1) ~ 3,
missing_vars == 1 & (X1 == 2 & X2 == 1 & X3 == 1 & is.na(X4)) ~ 3,
missing_vars == 1 & (is.na(X1) & X2 == 1 & X3 == 2 & X4 == 1) ~ 3,
missing_vars == 1 & (X1 == 1 & is.na(X2) & X3 == 2 & X4 == 1) ~ 3,
missing_vars == 1 & (X1 == 1 & X2 == 2 & is.na(X3) & X4 == 1) ~ 3,
missing_vars == 1 & (X1 == 1 & X2 == 2 & X3 == 1 & is.na(X4)) ~ 3,
missing_vars == 1 & (is.na(X1) & X2 == 1 & X3 == 1 & X4 == 1) ~ 4,
missing_vars == 1 & (X1 == 1 & is.na(X2) & X3 == 1 & X4 == 1) ~ 4,
missing_vars == 1 & (X1 == 1 & X2 == 1 & is.na(X3) & X4 == 1) ~ 4,
missing_vars == 1 & (X1 == 1 & X2 == 1 & X3 == 1 & is.na(X4)) ~ 4))
Я повторяю это с каждой комбинацией для 2 NA, 3 NA, а затем 4 NA, а затем суммирую «zero_na», «one_na» и т. д., чтобы получить окончательный подсчет значения под X11.
Однако в настоящее время у меня есть около 300 000 наблюдений, и мне нужно сделать это по 7 различным переменным с разным количеством NA, 1 и 2. Мне придется написать нелепое количество комбинаций, и я просто хотел знать, есть ли более эффективный способ написания этого кода?
Заранее большое спасибо!





Попробуйте это:
df["X11"] = apply(df[,c(1:4)],1,\(s) sum(s==1,na.rm=T))
Вы можете добиться того же результата, используя rowwise() и c_across(), если вы неравнодушны к решению dplyr.
df %>% rowwise() %>% mutate(x11 = sum(c_across(X1:X4)==1, na.rm=T))
Выход:
X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11
1 1 1 NA 1 NA NA NA 1 1 2 3
2 NA 1 1 NA 2 NA 2 2 NA 1 2
3 1 NA 1 1 NA NA 1 2 NA 1 3
4 2 2 2 1 1 2 1 NA 2 2 1
5 NA 2 NA 2 NA 2 1 NA 1 1 0
6 2 2 1 1 2 NA 1 2 1 1 2
7 1 2 NA NA 2 1 1 NA NA 1 1
8 2 2 NA NA 1 NA NA 2 NA 1 0
9 1 NA 1 2 2 1 2 NA NA 1 2
10 NA 2 1 NA NA NA NA 2 2 NA 1
Спасибо! В итоге я использовал: df <- df %>% mutate(X11 = rowSums(across(X1:X4)==1, na.rm=T)) потому что rowwise() и c_across() заняли немного больше времени. Я ценю вашу помощь!!!
Просто используйте rowSums():
df$X11 = rowSums(df[1L:4L] == 1L, na.rm = TRUE)
df
#> X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11
#> 1 1 1 NA 1 NA NA NA 1 1 2 3
#> 2 NA 1 1 NA 2 NA 2 2 NA 1 2
#> 3 1 NA 1 1 NA NA 1 2 NA 1 3
#> 4 2 2 2 1 1 2 1 NA 2 2 1
#> 5 NA 2 NA 2 NA 2 1 NA 1 1 0
#> 6 2 2 1 1 2 NA 1 2 1 1 2
#> 7 1 2 NA NA 2 1 1 NA NA 1 1
#> 8 2 2 NA NA 1 NA NA 2 NA 1 0
#> 9 1 NA 1 2 2 1 2 NA NA 1 2
#> 10 NA 2 1 NA NA NA NA 2 2 NA 1
и укажите na.rm = TRUE.
Примечание
Предоставленные данные
df = read.table(text = " X1 X2 X3 X4 X5 X6 X7 X8 X9 X10
1 1 1 NA 1 NA NA NA 1 1 2
2 NA 1 1 NA 2 NA 2 2 NA 1
3 1 NA 1 1 NA NA 1 2 NA 1
4 2 2 2 1 1 2 1 NA 2 2
5 NA 2 NA 2 NA 2 1 NA 1 1
6 2 2 1 1 2 NA 1 2 1 1
7 1 2 NA NA 2 1 1 NA NA 1
8 2 2 NA NA 1 NA NA 2 NA 1
9 1 NA 1 2 2 1 2 NA NA 1
10 NA 2 1 NA NA NA NA 2 2 NA", header = TRUE)
Вот трюк с ^ + is.na + rowSums
> df$X11 <- rowSums(!is.na(df[1:4]^NA))
> df
X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11
1 1 1 NA 1 NA NA NA 1 1 2 3
2 NA 1 1 NA 2 NA 2 2 NA 1 2
3 1 NA 1 1 NA NA 1 2 NA 1 3
4 2 2 2 1 1 2 1 NA 2 2 1
5 NA 2 NA 2 NA 2 1 NA 1 1 0
6 2 2 1 1 2 NA 1 2 1 1 2
7 1 2 NA NA 2 1 1 NA NA 1 1
8 2 2 NA NA 1 NA NA 2 NA 1 0
9 1 NA 1 2 2 1 2 NA NA 1 2
10 NA 2 1 NA NA NA NA 2 2 NA 1
Это сработало. Спасибо!!
Возможно, другой способ сформулировать это так: «если 1 НП, то сколько единиц в оставшихся выбранных столбцах; если 2 НП, то сколько двойок в оставшихся выбранных столбцах; если 3 НП , тогда сколько единиц в остальных выбранных столбцах?"