已更新,可在新变量中包含多个选项:
我正在处理一个混乱的大数据患者文件(> 4000万行)。每个患者(id
)有几行。每行(大致)代表一个带有症状/疾病代码(icpc
)的咨询。我添加了一个新列,其中包含针对特定疾病患者的类别(基于列icpc
和icpc2
)。
我的原始data.frame(df
)看起来像这样(这是伪造的数据,id
在我的数据集中更长了,我忽略了我想删除的无关列):< / p>
id icpc icpc2 reg.date
1: 123 D95 F15 19JUN2015
2: 123 F85 15AUG2016
3: 332 A01 16MAR2010
4: 332 A04 20JAN2018
5: 332 K20 20FEB2017
6: 100 B10 01JUN2017
7: 100 A04 11JAN2008
8: 113 T08 18MAR2018
9: 113 P28 19JAN2017
10: 113 D95 A01 16JAN2013
11: 113 A04 01MAY2009
12: 551 B12 A01 03APR2011
13: 551 D95 09MAY2015
说我想将D95
和/或A01
的患者在名为“ condit”的新列中分类为是(基于两列icpc
和icpc2
) 。以下作品:
cond1 <- c("D95", "A01")
setDT(df)[, condit := ifelse(any(icpc %in% cond1 | icpc2 %in% cond1), "yes","no"), by=id]
df
但是现在我想在新列icpc
中将icpc2
和condit
中的几个代码分类。因此,例如,来自icpc
或icpc2
的D95和/或A01为A
,A04
和/或T08
为B
,{{ 1}}作为B10
中的C
。注意:condit
应该覆盖A
(请参见第4、8和11行),B
应该覆盖B
等(因为id可能属于多个类别)
这是我想要的data.frame(C
):
df
任何帮助将不胜感激。谢谢!
答案 0 :(得分:2)
我认为你应该写:
df.cat <- df %>%
group_by(id) %>%
mutate(condit =
if_else((icpc %in% c("D95", "A01")) | (icpc2 %in% c("D95", "A01")) ~ 'yes', 'no'))
当可能有多个选择时,请勿使用==
。顺便说一句,我在您的逻辑比较中添加了括号
答案 1 :(得分:1)
对于大型(> 4000万行)数据集, data.table 包可能是一个不错的选择:
library(data.table)
cond1 <- c("D95", "A01")
setDT(df)[, condit := ifelse(any(icpc %in% cond1 | icpc2 %in% cond1), "yes","no"), by=id]
df
id icpc icpc2 reg.date condit
1: 123 D95 F15 19JUN2015 yes
2: 123 F85 15AUG2016 yes
3: 332 A01 16MAR2010 yes
4: 332 A04 20JAN2018 yes
5: 332 K20 20FEB2017 yes
6: 100 B10 01JUN2017 no
7: 100 A04 11JAN2008 no
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
数据:
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))
修改:针对多种情况:
cond1 <- c("D95", "A01") # A
cond2 <- c("A04", "T08") # B
cond3 <- "B10" # C
setDT(df)[, condit := if(any(icpc %in% cond1 | icpc2 %in% cond1)) "A" else
if(any(icpc %in% cond2 | icpc2 %in% cond2)) "B" else
if(any(icpc %in% cond3 | icpc2 %in% cond3)) "C" else "", by=id]
id icpc icpc2 reg.date condit
1: 123 D95 F15 19JUN2015 A
2: 123 F85 15AUG2016 A
3: 332 A01 16MAR2010 A
4: 332 A04 20JAN2018 A
5: 332 K20 20FEB2017 A
6: 100 B10 01JUN2017 B
7: 100 A04 11JAN2008 B
8: 113 T08 18MAR2018 A
9: 113 P28 19JAN2017 A
10: 113 D95 A01 16JAN2013 A
11: 113 A04 01MAY2009 A
12: 551 B12 B10 03APR2011 C
13: 551 D96 09MAY2015 C
数据 :(由于未找到“ C”条件,因此与原始数据略有修改。
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",
"D96"), icpc2 = c("F15", "", "", "", "", "", "", "", "", "A01",
"", "B10", ""), reg.date = c("19JUN2015", "15AUG2016", "16MAR2010",
"20JAN2018", "20FEB2017", "01JUN2017", "11JAN2008", "18MAR2018",
"19JAN2017", "16JAN2013", "01MAY2009", "03APR2011", "09MAY2015"
)), class = "data.frame", row.names = c(NA, -13L))
在具有40M行的数据帧上进行了测试: system.time(...)
# user system elapsed
# 111.11 1.17 111.97
使用dplyr:
# Error: cannot allocate vector of size 274.7 Mb
# Timing stopped at: 4.19 1.11 5.39
答案 2 :(得分:1)
由于要为整个组分配值,因此需要使用any
,因为已经发现了。
library(dplyr)
df %>%
group_by(id) %>%
mutate(condit = if(any(icpc %in% c("D95", "A01") | icpc2 %in% c("D95", "A01")))
"yes" else "no")
或者没有if
/ else
的更快的选择将是
df %>%
group_by(id) %>%
mutate(condit = c("no", "yes")[(any(icpc %in% c("D95", "A01") |
icpc2 %in% c("D95", "A01"))) + 1])
答案 3 :(得分:1)
检查c(icpc, icpc2)
的任何元素是否在所需的代码中。请注意,结果是一个简单的字符串yes
或no
,因此我们可以只使用if
而不是if_else
。
DF %>%
group_by(id) %>%
mutate(condit = if (any(c(icpc, icpc2) %in% c("D95", "A01"))) "yes" else "no") %>%
ungroup
第二种方法是将数据转换为长格式,在这种情况下,将只有一个icpc列(称为value
),设置condit
然后再转换回宽格式(否则您可能会想要保留它的长格式)。最后的select
对各列进行重新排序,使其顺序与输入顺序相同,即id列在第一位,icpc列在第二位,依此类推。
library(tidyr)
DF %>%
pivot_longer(starts_with("icpc")) %>%
filter(name != "") %>%
group_by(id) %>%
mutate(condit = if (any(value %in% c("D95", "A01"))) "yes" else "no") %>%
pivot_wider %>%
select(names(DF))
可重复输入的形式假定为:
Lines <- "id icpc icpc2 reg.date
123 D95 F15 19JUN2015
123 F85 15AUG2016
332 A01 16MAR2010
332 A04 20JAN2018
332 K20 20FEB2017
100 B10 01JUN2017
100 A04 11JAN2008
113 T08 18MAR2018
113 P28 19JAN2017
113 D95 A01 16JAN2013
113 A04 01MAY2009
551 B12 A01 03APR2011
551 D95 09MAY2015"
L <- readLines(textConnection(Lines))
L <- sub(" (\\S+) ", ",\\1,", L)
L <- sub(" +", ",", L)
DF <- read.csv(text = L, check.names = FALSE, as.is = TRUE, strip.white = TRUE)