根据 R 列中的部分匹配创建新变量
Posted
技术标签:
【中文标题】根据 R 列中的部分匹配创建新变量【英文标题】:Create new variable based on partial matching in column R 【发布时间】:2020-04-01 17:48:49 【问题描述】:我正在尝试根据以下数据在 data.frame 中创建一个新变量:
df <- structure(list(id = c(123L, 123L, 332L, 332L, 332L, 100L, 100L,
113L, 113L, 113L, 113L, 551L, 551L), icpc = c("D95", "F85", "A01",
"A04", "K20", "B10", "A04", "T08", "P28", "D95", "A04", "B12",
"D95"), icpc2 = c("F15", "", "", "", "", "", "", "", "", "A01",
"", "A01", ""), reg.date = c("19JUN2015", "15AUG2016", "16MAR2010",
"20JAN2018", "20FEB2017", "01JUN2017", "11JAN2008", "18MAR2018",
"19JAN2017", "16JAN2013", "01MAY2009", "03APR2011", "09MAY2015"
)), class = "data.frame", row.names = c(NA, -13L))
我已经为新列condit
使用了以下代码:
library(data.table)
cond1 <- c("D95", "A01")
setDT(df)[, condit := ifelse(any(icpc %in% cond1 | icpc2 %in% cond1), "yes","no"), by=id]
df
但是,我正在处理一个大型数据集 (>4000 万),并且还想根据 icpc
和 icpc2
中的字母进行分类。
我的目标是添加一个新列,其中包含yes
或no
的字母A
(因此,A01
、A04
、A50
等)列icpc
或icpc2
。我还希望所有具有相同id
的列在新列condit2
中都有yes
。
我正在尝试以下方法:
df2 <- setDT(df)[, condit2 := ifelse
(any(icpc %in% pmatch("K", df) | icpc2 %in% pmatch("K", df)), "yes","no"), by = PATNR]
head(df2)
这一直在运行......(我想,无论如何,df 太面包了,如果应该是 df$icpc
和 df$icpc2
?)
比以下检查pmatch
是否合适:
condit2 <- pmatch("K")
然后看着完全不同的东西:
library(sqldf)
condit2 <- sqldf("df$icpc | df$icpc2, '%K%'")
这应该会产生以下数据框:
id icpc icpc2 reg.date condit2
1: 123 D95 F15 19JUN2015 no
2: 123 F85 15AUG2016 no
3: 332 A01 16MAR2010 yes
4: 332 A04 20JAN2018 yes
5: 332 K20 20FEB2017 yes
6: 100 B10 01JUN2017 yes
7: 100 A04 11JAN2008 yes
8: 113 T08 18MAR2018 yes
9: 113 P28 19JAN2017 yes
10: 113 D95 A01 16JAN2013 yes
11: 113 A04 01MAY2009 yes
12: 551 B12 A01 03APR2011 yes
13: 551 D95 09MAY2015 yes
谁能给个提示?谢谢!!
【问题讨论】:
【参考方案1】:setDT(df)
to_check <- 'A'
df[, condit2 := fifelse(any(grepl(to_check, icpc) | grepl(to_check, icpc2)),
'yes', 'no'),
by = id]
df
# id icpc icpc2 reg.date condit2
# 1: 123 D95 F15 19JUN2015 no
# 2: 123 F85 15AUG2016 no
# 3: 332 A01 16MAR2010 yes
# 4: 332 A04 20JAN2018 yes
# 5: 332 K20 20FEB2017 yes
# 6: 100 B10 01JUN2017 yes
# 7: 100 A04 11JAN2008 yes
# 8: 113 T08 18MAR2018 yes
# 9: 113 P28 19JAN2017 yes
# 10: 113 D95 A01 16JAN2013 yes
# 11: 113 A04 01MAY2009 yes
# 12: 551 B12 A01 03APR2011 yes
# 13: 551 D95 09MAY2015 yes
如果,而不是只有两列 icpc
和 icpc2
,你有一堆,不想为每一个都输入 grepl
代码,这里是带有 .SDcols
的版本,它给出了同样的结果。
df[, condit2 := fifelse(any(Reduce('|', lapply(.SD, grepl, patt = to_check))),
'yes', 'no'),
by = id, .SDcols = patterns('icpc')]
【讨论】:
这是针对列,而不是列中的值,对吧? 它正在检查列值以查看它们是否包含“A” 太好了,我现在看到了。为选择列提供额外的选项。超好的。谢谢! 顺便说一句,fifelse 应该是 ifelse fifelse 是一个 data.table 函数,类似于 ifelse,但速度更快(因此前面有 f)【参考方案2】:使用dplyr
,可以通过以下方法完成:
group_by(id)
、paste
将感兴趣的两列放在一起,使用sum
和grepl
检查连接的字符串中是否至少出现了一个A
。
library(dplyr)
df %>%
group_by(id) %>%
mutate(condit2 = case_when(sum(grep("A", paste(icpc, icpc2))) > 0 ~ "yes",
TRUE ~ "no")) %>%
ungroup()
id icpc icpc2 reg.date condit2
<int> <chr> <chr> <chr> <chr>
1 123 D95 "F15" 19JUN2015 no
2 123 F85 "" 15AUG2016 no
3 332 A01 "" 16MAR2010 yes
4 332 A04 "" 20JAN2018 yes
5 332 K20 "" 20FEB2017 yes
6 100 B10 "" 01JUN2017 yes
7 100 A04 "" 11JAN2008 yes
8 113 T08 "" 18MAR2018 yes
9 113 P28 "" 19JAN2017 yes
10 113 D95 "A01" 16JAN2013 yes
11 113 A04 "" 01MAY2009 yes
12 551 B12 "A01" 03APR2011 yes
13 551 D95 "" 09MAY2015 yes
【讨论】:
以上是关于根据 R 列中的部分匹配创建新变量的主要内容,如果未能解决你的问题,请参考以下文章
在 Shiny 中使用部分 textInput 作为 R 中的变量