提问人:larsroarf 提问时间:11/9/2023 最后编辑:larsroarf 更新时间:11/9/2023 访问量:85
如何根据 R 中其他因子列的信息创建新列?
How to create a new column based on information from other factor columns in R?
问:
一段时间以来,我一直试图找到一个有效的解决方案,用于如何根据 R 中其他因子列的信息创建新列。我提出了一个可行的解决方案,但非常乏味,而一个远不那么乏味但只能部分有效的解决方案。我通常使用包含NA的调查数据,这是问题的重要组成部分。如果我在提出这个问题时做错了什么,请原谅我,因为这既是我在 SO 的第一篇文章,也是我的第一个 Reprex。这个问题与 SO 提出的其他问题类似,但我无法调整任何现有的解决方案来解决我的问题。
[由于不清楚,在第一次响应后编辑] 我想要得到的是我的 tible 中的一个新列,它仅在用于生成新列的所有列都是 NA 时返回 NA,而如果至少一列是“yes”,则返回“yes”,如果没有列包含“yes”,则返回“no”。
这里有一个 Reprex 来说明我的问题:
library(tidyverse)
# create the table
df <- tibble(
othervar_2007 = c(NA, "yes", "no", "no", "no"),
morv1_2007 = c(NA, "yes", "no", "no", NA),
morv2_2007 = c(NA, "yes", NA, "no", "no"),
morv3_2007 = c(NA, "no", "yes", "no", "no"),
morv4_2007 = c(NA, "no", "no", "no", "no"),
morv_othervar = c(NA, "yes", "no", "no", "no")
)
# show table
df
#> # A tibble: 5 × 6
#> othervar_2007 morv1_2007 morv2_2007 morv3_2007 morv4_2007 morv_othervar
#> <chr> <chr> <chr> <chr> <chr> <chr>
#> 1 <NA> <NA> <NA> <NA> <NA> <NA>
#> 2 yes yes yes no no yes
#> 3 no no <NA> yes no no
#> 4 no no no no no no
#> 5 no <NA> no no no no
# alternative 1
df <- df %>%
mutate(newvar1 = case_when(
morv1_2007 == "yes" | morv2_2007 == "yes" | morv3_2007 == "yes" | morv4_2007 == "yes" ~ "Yes",
morv1_2007 == "no" | morv2_2007 == "no" | morv3_2007 == "no" | morv4_2007 == "no" ~ "No")
)
df %>%
count(newvar1)
#> # A tibble: 3 × 2
#> newvar1 n
#> <chr> <int>
#> 1 No 2
#> 2 Yes 2
#> 3 <NA> 1
# alternative 2
df <- df %>%
rowwise %>%
mutate(newvar2 = if_else(rowSums(across(c(morv1_2007, morv2_2007, morv3_2007, morv4_2007), ~ .x == "yes"))>0, "Yes", "No"))
df %>%
count(newvar2)
#> # A tibble: 3 × 2
#> # Rowwise:
#> newvar2 n
#> <chr> <int>
#> 1 No 1
#> 2 Yes 1
#> 3 <NA> 3
Created on 2023-11-09 with reprex v2.0.2
Tibble 包含四列,这些列应该用于改变新列,以及两个模拟列,它们应该保持原样。命名这些列也是为了说明相关列的选择问题。
标记为备选方案 1 的解决方案有效,但当要从中获取信息的列数变大时,该解决方案非常繁琐。我也无法找到选择列的好解决方案,例如,通过使用 starts_with 和 ends_with。
但是,如果至少一列为 NA,则标记为备选方案 2 的解决方案将返回 NA。当添加 na.rm = TRUE 时,它对仅包含 NA 的行返回“否”。选择问题也适用于此处。
希望在R和编码方面更有经验的人可以帮助我。
编辑后续 TIDYVERSE 解决方案
df <- df %>%
rowwise %>%
mutate(newvar3 = if(all(is.na(c_across(matches("^morv.*2007$"))))) {
NA_character_
} else if ("yes" %in% c_across("^morv.*2007$"))) {
"yes"
} else {
"no"})
这返回了我所追求的,但速度很慢。这里建议的代码要快得多。
答:
基于
“这是我想得到的 [...]:我脑海中的一个新专栏 仅当用于生成新列的所有列都使用时才返回 是 NA,如果至少有一个“yes”,则返回“yes”,如果没有,则返回“no” 列包含“yes”。
NA
请注意,我已更改为“否”以进行测试。df[1, 1]
df[1, 1] <- "no"
我建议采用以下方法:
df$newvar <-
apply(X = df[, grepl("morv\\d{1}", colnames(df))],
MARGIN = 1L,
FUN = \(x) ifelse(
test = all(is.na(x)),
yes = NA,
no = ifelse(
test = any(x == "yes", na.rm = TRUE),
yes = "yes",
no = "no")
)
)
这给了
> df
# A tibble: 5 × 7
othervar_2007 morv1_2007 morv2_2007 morv3_2007 morv4_2007 morv_othervar newvar
<chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 no NA NA NA NA NA NA
2 yes yes yes no no yes yes
3 no no NA yes no no yes
4 no no no no no no no
5 no NA no no no no no
评论
na.rm = TRUE
any()
评论