提问人:talocodat 提问时间:11/6/2023 最后编辑:talocodat 更新时间:11/7/2023 访问量:85
将 str_detect() 与 dplyr::mutate 一起使用
Using str_detect() rowwise with dplyr::mutate
问:
我正在尝试使用 dplyr::mutate() 在数据帧中创建一个新列。 对于从中获取数据的列,有两种情况:
- 原始列(“cabin”)包含字母和数字的一种组合,例如“E4”。在这种情况下,新列应为“E”。
- 原始列包含两个以上的字母和数字组合,例如“F G73”或“B57 B59 B63 B66”。在这种情况下,新列应分别为“F、G”或“B”。
数据示例:
structure(list(pclass = c(1L, 1L, 1L, 3L, 3L), survived = c(0L,
1L, 1L, 0L, 0L), name = c("Allison, Miss. Helen Loraine", "Anderson, Mr. Harry",
"Andrews, Miss. Kornelia Theodosia", "Moen, Mr. Sigurd Hansen",
"Soholt, Mr. Peter Andreas Lauritz Andersen"), sex = c("female",
"male", "female", "male", "male"), age = c(2, 48, 63, 25, 19),
sibsp = c(1L, 0L, 1L, 0L, 0L), parch = c(2L, 0L, 0L, 0L,
0L), ticket = c("113781", "19952", "13502", "348123", "348124"
), fare = c(151.55, 26.55, 77.9583, 7.65, 7.65), cabin = c("C22 C26",
"E12", "D7", "F G73", "F G73"), embarked = c("S", "S", "S",
"S", "S"), boat = c("", "3", "10", "", ""), body = c(NA,
NA, NA, 309L, NA), home.dest = c("Montreal, PQ / Chesterville, ON",
"New York, NY", "Hudson, NY", "", ""), title = c("Miss.",
"Mr.", "Miss.", "Mr.", "Mr.")), row.names = c("3", "6", "7",
"1025", "1218"), class = "data.frame")
这是我使用的代码:
titanic_data <- titanic_data %>%
mutate(cabin_zone = ifelse(str_detect(cabin," "),
cabin %>%
str_extract("[A-Z]") %>%
str_split(.," ") %>%
unlist(.) %>%
unique(.) %>%
paste(.,collapse = ","),
gsub("[0-9 ]", "", cabin)))
第二种情况的结果很好,但对于第一种情况,我总是得到这个字符串作为结果:'B,C,E,D,A,NA,T,F,G'。
我无法弄清楚为什么操作没有按我想要的方式工作!任何帮助都值得赞赏!
答:
3赞
Andy Baxter
11/6/2023
#1
我认为您面临的关键问题是,要对每一行进行整列评估,并仅提取每位乘客的第一个相关字母。 提取每行中的每个匹配项,并返回字符向量列表(需要折叠)。这应该起作用:cabin %>% str_extract()...
str_extract_all
经过编辑以确保与 tibbles 兼容:
library(tidyverse)
titanic_data %>%
as_tibble() |>
mutate(cabin_zone = str_extract_all(cabin, "[A-Z]") |>
lapply(unique) |>
vapply(paste, character(1), collapse = ", ")) |>
select(name, cabin, cabin_zone)
#> # A tibble: 5 × 3
#> name cabin cabin_zone
#> <chr> <chr> <chr>
#> 1 Allison, Miss. Helen Loraine C22 C26 C
#> 2 Anderson, Mr. Harry E12 E
#> 3 Andrews, Miss. Kornelia Theodosia D7 D
#> 4 Moen, Mr. Sigurd Hansen F G73 F, G
#> 5 Soholt, Mr. Peter Andreas Lauritz Andersen F G73 F, G
# Selected some columns for simplicity
函数 和 使 和 函数在每一行中单独工作(通过遍历匹配项列表)。如果您更喜欢 tidyverse 函数,您可以使用以下命令编写以下步骤以返回字符列:lapply
vapply
unique
paste
map
titanic_data %>%
as_tibble() |>
mutate(cabin_zone = str_extract_all(cabin, "[A-Z]") |>
map_chr(compose(\(x) paste(x, collapse = ", "), unique))) |>
select(name, cabin, cabin_zone)
#> # A tibble: 5 × 3
#> name cabin cabin_zone
#> <chr> <chr> <chr>
#> 1 Allison, Miss. Helen Loraine C22 C26 C
#> 2 Anderson, Mr. Harry E12 E
#> 3 Andrews, Miss. Kornelia Theodosia D7 D
#> 4 Moen, Mr. Sigurd Hansen F G73 F, G
#> 5 Soholt, Mr. Peter Andreas Lauritz Andersen F G73 F, G
或者,您可以使用隔离处理每一行,并从那里折叠它们:rowwise()
titanic_data |>
as_tibble() |>
rowwise() |>
mutate(cabin_zone = str_extract_all(cabin, "[A-Z]") |>
unlist() |>
unique() |>
paste(collapse = ", ")) |>
select(name, cabin, cabin_zone)
#> # A tibble: 5 × 3
#> # Rowwise:
#> name cabin cabin_zone
#> <chr> <chr> <chr>
#> 1 Allison, Miss. Helen Loraine C22 C26 C
#> 2 Anderson, Mr. Harry E12 E
#> 3 Andrews, Miss. Kornelia Theodosia D7 D
#> 4 Moen, Mr. Sigurd Hansen F G73 F, G
#> 5 Soholt, Mr. Peter Andreas Lauritz Andersen F G73 F, G
评论
1赞
talocodat
11/6/2023
谢谢!有没有办法在没有 lapply() 和 vapply() 的情况下在每一行上使用 str_extract_all()?
0赞
Andy Baxter
11/6/2023
是的,对不起,还有它将单独处理每一行(请参阅我刚刚在上面添加的第三个示例)。 仍然为每列返回一个长度为 1 的列表,该列表需要 ed 作为上面的代码。这也许使它更具可读性!rowwise
str_extract_all
unlist
评论
dput(titanic_data)
dput(titanic_data[c(1,5,7),])