pat*_*656 7 r dplyr tidyverse mutate
我在数据帧中有一系列变量(超过100个),并且我想创建一个指示符变量,以了解任何变量中是否存在特定的文本模式。以下是具有三个变量的示例。我发现的一种解决方案是使用,tidyr::unite()然后使用dplyr::mutate(),但是我对不必统一变量的解决方案感兴趣。
c1<-c("T1", "X1", "T6", "R5")
c2<-c("R4", "C6", "C7", "X3")
c3<-c("C5", "C2", "X4", "T2")
df<-data.frame(c1, c2, c3)
c1 c2 c3
1 T1 R4 C5
2 X1 C6 C2
3 T6 C7 X4
4 R5 X3 T2
code.vec<-c("T1", "T2", "T3", "T4") #Text patterns of interest
code_regex<-paste(code.vec, collapse="|")
new<-df %>%
unite(all_c, c1:c3, remove=FALSE) %>%
mutate(indicator=if_else(grepl(code_regex, all_c), 1, 0)) %>%
select(-(all_c))
c1 c2 c3 indicator
1 T1 R4 C5 1
2 X1 C6 C2 0
3 T6 C7 X4 0
4 R5 X3 T2 1
Run Code Online (Sandbox Code Playgroud)
上面是产生所需结果的示例,但是我觉得应该有一种tidyverse不必合并变量就可以做到这一点的方法。SAS使用ARRAY语句和DO循环可以很轻松地处理此问题,我希望R具有处理此问题的好方法。
实际的数据框除了要搜索的“ c”字段之外,还有许多其他变量,因此涉及搜索每一列的解决方案将需要将数据框设置为首先仅包含我要搜索的变量,然后再将数据与其他联接在一起变量。
使用基数R,我们可以使用sapply和用于grepl在每列中查找模式,并将1分配给匹配项大于0的行。
df$indicator <- as.integer(rowSums(sapply(df, grepl, pattern = code_regex)) > 0)
df
# c1 c2 c3 indicator
#1 T1 R4 C5 1
#2 X1 C6 C2 0
#3 T6 C7 X4 0
#4 R5 X3 T2 1
Run Code Online (Sandbox Code Playgroud)
如果其他列很少,我们有兴趣仅将其应用于以开头的列,"c"我们可以使用grep它们进行过滤。
cols <- grep("^c", names(df))
as.integer(rowSums(sapply(df[cols], grepl, pattern = code_regex)) > 0)
Run Code Online (Sandbox Code Playgroud)
使用dplyr我们可以做到的
library(dplyr)
df$indicator <- as.integer(df %>%
mutate_at(vars(c1:c3), ~grepl(code_regex, .)) %>%
rowSums() > 0)
Run Code Online (Sandbox Code Playgroud)
我们可以用tidyverse
library(tidyverse)
df %>%
mutate_all(str_detect, pattern = code_regex) %>%
reduce(`+`) %>%
mutate(df, indicator = .)
# c1 c2 c3 indicator
#1 T1 R4 C5 1
#2 X1 C6 C2 0
#3 T6 C7 X4 0
#4 R5 X3 T2 1
Run Code Online (Sandbox Code Playgroud)
或者使用base R
Reduce(`+`, lapply(df, grepl, pattern = code_regex))
#[1] 1 0 0 1
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
315 次 |
| 最近记录: |