【发布时间】:2021-05-14 14:18:13
【问题描述】:
这是我正在做的一个例子。 data.frames 通常有数千条记录,而且我经常尝试使用if() 语句来满足更多条件。
library(tidyverse)
# example df 1
coll <- data.frame(id = c("alpha", "alpha", "beta", "beta", "gamma", "delta", "epsilon"),
frequency = c("12.340", "23.340", "12.560", "15.670", "56.230", "12.890", "89.430"),
start = c("2010-01-01", "2015-01-01", "2011-02-02", "2017-02-02", rep("2019-01-01", 3)),
end = c("2011-02-02", NA, "2012-01-01", NA, "2018-02-02", rep(NA, 2))) %>%
mutate(still.active = ifelse(!is.na(end), still.active <- "No", NA),
reason = ifelse(!is.na(end), reason <- "Removed", NA)) %>%
mutate_all(as.character)
# example df 2
mort <- data.frame(id = c("alpha", "beta", "gamma", "delta", "zeta"),
frequency = c("23.340", "15.670", "56.230", "12.890", NA),
date = c("2016-01-01", "2018-01-01", rep("2020-01-01", 3)),
type = c(rep(1, 2), rep(2, 3))
) %>%
mutate_all(as.character)
for(i in 1:nrow(coll)){
for(j in 1:nrow(mort)){
if(coll$id[i] == mort$id[j] & # if these match
coll$frequency[i] == mort$frequency[j] & # and these match
is.na(coll$end[i]) & # and the value I want to fill in is currently blank
mort$type[j] == "1" # and this other condition is met
){
coll$end[i] <- as.character(mort$date[j]) # then assign these cells these values
coll$still.active[i] <- "No"
coll$reason[i] <- "Said so"
}
}
}
嵌套的 for 循环正是我所需要的,但在实践中它们变得非常慢,我想学习一种更好的方法。当只需在两个 data.frames 中匹配一列的值时,索引很容易,例如:
df <- data.frame(id = c("one", "two", "three")) %>% arrange(desc(id))
df2 <- data.frame(id = c("one", "two", "three"),
frequency = c("23.340", "15.670", "56.230"))
df$freq <- df2[match(df$id, df2$id), "frequency"]
但我不知道在有更多条件时如何到达那里,即使我可以,我认为其他人可能很难阅读并弄清楚发生了什么。我喜欢嵌套 for 循环的一件事是它相当容易阅读。或者也许我只是习惯了他们。
我可以使用嵌套的ifelse() 语句来代替吗?还有哪些其他选择?
【问题讨论】:
-
不确定,但可能是“变异连接”(例如 dplyr 的 inner_join 是解决方案的一部分。
标签: r performance dataframe for-loop conditional-statements