在 dplyr 的特定列范围内使用 mutate case_when()
Use mutate case_when() in a specific range of columns in dplyr
我有一个看起来像 df1 的大数据框。
如果任何字符包含字符串 S,我想在 col2:col4 (col2,col3,col4) 之间的列范围内搜索。
library(tidyverse)
df <- tibble(position=c(100,200,300),
correction=c("62M89S",
"8M1D55M88S",
"1S25M1S36M89S"))
df1 <- df %>%
separate(correction, into = str_c("col", 1:5),
sep = "(?<=\D)(?=\d)", fill = "left", remove = FALSE)
df1
#> # A tibble: 3 × 7
#> position correction col1 col2 col3 col4 col5
#> <dbl> <chr> <chr> <chr> <chr> <chr> <chr>
#> 1 100 62M89S <NA> <NA> <NA> 62M 89S
#> 2 200 8M1D55M88S <NA> 8M 1D 55M 88S
#> 3 300 1S25M1S36M89S 1S 25M 1S 36M 89S
由 reprex package (v2.0.1)
创建于 2022-03-12
我希望我的数据看起来像这样
df1
#> position correction col1 col2 col3 col4 col5 inner_S
#> <dbl> <chr> <chr> <chr> <chr> <chr> <chr>
#> 1 100 62M89S <NA> <NA> <NA> 62M 89S NO
#> 2 200 8M1D55M88S <NA> 8M 1D 55M 88S NO
#> 3 300 1S25M1S36M89S 1S 25M 1S 36M 89S YES
因为在col3.
中有字符1S
我试过了,但我确定我违反了一些属性
df1 %>%
mutate_at(vars(col2:col4),
~inner_S=case_when(grepl("S",.) ~ "Yes",
TRUE ~ "No"
))
dplyr 的 c_across
对于这样的操作非常方便:
df1 %>%
rowwise() %>%
mutate(inner_S = ifelse(any(grepl('S', c_across(col1:col4))), 'YES', 'NO'))
position correction col1 col2 col3 col4 col5 inner_S
<dbl> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 100 62M89S NA NA NA 62M 89S NO
2 200 8M1D55M88S NA 8M 1D 55M 88S NO
3 300 1S25M1S36M89S 1S 25M 1S 36M 89S YES
jdobres 的回答很完美。这是一个更复杂的使用 across
:
library(tidyverse)
df1 %>%
mutate(across(col1:col4, ~ifelse(
str_detect(., 'S'), TRUE, FALSE), .names = 'new_{col}')) %>%
unite(inner_S, starts_with('new'), na.rm = TRUE, sep = ' ') %>%
mutate(inner_S = ifelse(str_detect(inner_S, 'TRUE'), "YES", "NO"))
position correction col1 col2 col3 col4 col5 inner_S
<dbl> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 100 62M89S NA NA NA 62M 89S NO
2 200 8M1D55M88S NA 8M 1D 55M 88S NO
3 300 1S25M1S36M89S 1S 25M 1S 36M 89S YES
请使用 data.table
找到另一个可能的解决方案
Reprex
- 代码
library(data.table)
setDT(df1)[, inner_S := apply(.SD, 1, function(x) fifelse(any(grepl("S", x)), "YES", "NO")), .SDcols = paste0("col", 2:4)][]
- 输出
#> position correction col1 col2 col3 col4 col5 inner_S
#> 1: 100 62M89S <NA> <NA> <NA> 62M 89S NO
#> 2: 200 8M1D55M88S <NA> 8M 1D 55M 88S NO
#> 3: 300 1S25M1S36M89S 1S 25M 1S 36M 89S YES
由 reprex package (v2.0.1)
于 2022 年 3 月 12 日创建
使用 rowwise
方法的替代方法(在处理较大的数据集时可能会非常昂贵)是对 TRUE
值求和。
df1 %>%
mutate(inner_S = ifelse(rowSums(across(col1:col4, str_detect, "S"), na.rm = T) > 1, "YES", "NO"))
我有一个看起来像 df1 的大数据框。 如果任何字符包含字符串 S,我想在 col2:col4 (col2,col3,col4) 之间的列范围内搜索。
library(tidyverse)
df <- tibble(position=c(100,200,300),
correction=c("62M89S",
"8M1D55M88S",
"1S25M1S36M89S"))
df1 <- df %>%
separate(correction, into = str_c("col", 1:5),
sep = "(?<=\D)(?=\d)", fill = "left", remove = FALSE)
df1
#> # A tibble: 3 × 7
#> position correction col1 col2 col3 col4 col5
#> <dbl> <chr> <chr> <chr> <chr> <chr> <chr>
#> 1 100 62M89S <NA> <NA> <NA> 62M 89S
#> 2 200 8M1D55M88S <NA> 8M 1D 55M 88S
#> 3 300 1S25M1S36M89S 1S 25M 1S 36M 89S
由 reprex package (v2.0.1)
创建于 2022-03-12我希望我的数据看起来像这样
df1
#> position correction col1 col2 col3 col4 col5 inner_S
#> <dbl> <chr> <chr> <chr> <chr> <chr> <chr>
#> 1 100 62M89S <NA> <NA> <NA> 62M 89S NO
#> 2 200 8M1D55M88S <NA> 8M 1D 55M 88S NO
#> 3 300 1S25M1S36M89S 1S 25M 1S 36M 89S YES
因为在col3.
中有字符1S我试过了,但我确定我违反了一些属性
df1 %>%
mutate_at(vars(col2:col4),
~inner_S=case_when(grepl("S",.) ~ "Yes",
TRUE ~ "No"
))
dplyr 的 c_across
对于这样的操作非常方便:
df1 %>%
rowwise() %>%
mutate(inner_S = ifelse(any(grepl('S', c_across(col1:col4))), 'YES', 'NO'))
position correction col1 col2 col3 col4 col5 inner_S
<dbl> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 100 62M89S NA NA NA 62M 89S NO
2 200 8M1D55M88S NA 8M 1D 55M 88S NO
3 300 1S25M1S36M89S 1S 25M 1S 36M 89S YES
jdobres 的回答很完美。这是一个更复杂的使用 across
:
library(tidyverse)
df1 %>%
mutate(across(col1:col4, ~ifelse(
str_detect(., 'S'), TRUE, FALSE), .names = 'new_{col}')) %>%
unite(inner_S, starts_with('new'), na.rm = TRUE, sep = ' ') %>%
mutate(inner_S = ifelse(str_detect(inner_S, 'TRUE'), "YES", "NO"))
position correction col1 col2 col3 col4 col5 inner_S
<dbl> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 100 62M89S NA NA NA 62M 89S NO
2 200 8M1D55M88S NA 8M 1D 55M 88S NO
3 300 1S25M1S36M89S 1S 25M 1S 36M 89S YES
请使用 data.table
Reprex
- 代码
library(data.table)
setDT(df1)[, inner_S := apply(.SD, 1, function(x) fifelse(any(grepl("S", x)), "YES", "NO")), .SDcols = paste0("col", 2:4)][]
- 输出
#> position correction col1 col2 col3 col4 col5 inner_S
#> 1: 100 62M89S <NA> <NA> <NA> 62M 89S NO
#> 2: 200 8M1D55M88S <NA> 8M 1D 55M 88S NO
#> 3: 300 1S25M1S36M89S 1S 25M 1S 36M 89S YES
由 reprex package (v2.0.1)
于 2022 年 3 月 12 日创建使用 rowwise
方法的替代方法(在处理较大的数据集时可能会非常昂贵)是对 TRUE
值求和。
df1 %>%
mutate(inner_S = ifelse(rowSums(across(col1:col4, str_detect, "S"), na.rm = T) > 1, "YES", "NO"))