r - 根据跨多列的条件将 df 中的值输入到新变量中
问题描述
我确信我不是唯一一个问过这个问题的人,但是经过数小时的搜索却没有运气,我需要自己问这个问题。
我有一个像这样的df(rp):
rp <- structure(list(agec1 = c(7, 16, 11, 11, 17, 17),
agec2 = c(6, 12, 9, 9, 16, 15),
agec3 = c(2, 9, 9, 9, 14, NA),
agec4 = c(NA, 7, 9, 9, 13, NA),
agec5 = c(NA, 4, 7, 7, 10, NA),
agec6 = c(NA, NA, 6, 6, 9, NA),
agec7 = c(NA, NA, NA, NA, 7, NA),
agec8 = c(NA, NA, NA, NA, 5, NA),
row.names = c(NA, -6L), class = c("tbl_df", "tbl", "data.frame"))
其中agecX中的每个obs指的是父母子女最多8个子女的年龄。我想创建一个新列“agec5_12”,其中包含 5-12 岁的最大孩子的年龄。所以我的 df 看起来像这样:
rpage <- structure(list(agec1 = c(7, 16, 11, 11, 17, 17),
agec2 = c(6, 12, 9, 9, 16, 15),
agec3 = c(2, 9, 9, 9, 14, NA),
agec4 = c(NA, 7, 9, 9, 13, NA),
agec5 = c(NA, 4, 7, 7, 10, NA),
agec6 = c(NA, NA, 6, 6, 9, NA),
agec7 = c(NA, NA, NA, NA, 7, NA),
agec8 = c(NA, NA, NA, NA, 5, NA),
agec5_12 = c(7, 12, 11, 11, 10, NA))
row.names = c(NA, -6L), class = c("tbl_df", "tbl", "data.frame"))
关于我的数据的注释:
- 年龄并不总是按相同的时间顺序排列,即从最年轻到最老或从最老到最年轻
- 一行可能没有年龄在此范围内的孩子(在这种情况下,我希望返回 NA)
我尝试编写一个函数并使用 and 应用rowwise
它mutate
:
fun.age5_12 <- function(x){
x[which(x == max(x[(x > 4) & (x < 13)], na.rm = TRUE))]
}
rpage <- rp %>%
select(-c(20:21, 199:200)) %>%
rowwise() %>%
mutate(agec5_12 = fun.age5_12(c(1:8)))
但是,这会将所有 obs 都返回为“12”。理想情况下,我想使用 dplyr 来做到这一点。任何使用mutate
或ifelse
不一定使用功能的建议都可以。
谢谢
解决方案
我知道你想要 tidyverse 但这是一种基本的 R 方式:
data.frame(
agec1 = c(7, 16, 11, 11, 17, 17),
agec2 = c(6, 12, 9, 9, 16, 15),
agec3 = c(2, 9, 9, 9, 14, NA),
agec4 = c(NA, 7, 9, 9, 13, NA),
agec5 = c(NA, 4, 7, 7, 10, NA),
agec6 = c(NA, NA, 6, 6, 9, NA),
agec7 = c(NA, NA, NA, NA, 7, NA),
agec8 = c(NA, NA, NA, NA, 5, NA),
stringsAsFactors = FALSE
) -> rp
for (i in 1:nrow(rp)) {
agec5_12 <- unlist(rp[i,], use.names = FALSE)
agec5_12 <- agec5_12[agec5_12 >= 5 & agec5_12 <= 12 & !is.na(agec5_12)]
rp[i, "agec5_12"] <- if (length(agec5_12)) max(agec5_12) else NA_integer_
}
rp
## agec1 agec2 agec3 agec4 agec5 agec6 agec7 agec8 agec5_12
## 1 7 6 2 NA NA NA NA NA 7
## 2 16 12 9 7 4 NA NA NA 12
## 3 11 9 9 9 7 6 NA NA 11
## 4 11 9 9 9 7 6 NA NA 11
## 5 17 16 14 13 10 9 7 5 10
## 6 17 15 NA NA NA NA NA NA NA
显示for
了成语,但sapply()
解决方案要快得多:
rp1$agec5_12 <- sapply(1:nrow(rp), function(i) {
agec5_12 <- unlist(rp[i,], use.names = FALSE)
agec5_12 <- agec5_12[agec5_12 >= 5 & agec5_12 <= 12 & !is.na(agec5_12)]
if (length(agec5_12)) max(agec5_12) else NA_integer_
})
推荐阅读
- google-chrome - 可以在选定的时间(离线)通知chrome通知吗?
- python - np.linalg.solve 和 scipy.linalg.cho_solve 之间的性能差距
- flask - 来自 Azure 容器的 Flask 的 send_from_directory
- python - 使用 matplotlib 问题显示两个数字
- javascript - 从 API 读取并比较日期以显示某些内容
- python - 如何从元素中获取文本值
- php - WordPress - WP_Widget:致命错误:未捕获的 ArgumentCountError:函数 WP_Widget::__construct() 的参数太少
- c - 如何在 C 中使用正则表达式/在哪里找到文件?
- c++ - 非成员运算符重载的运算符“==”不匹配
- bootstrap-4 - 如何以最小高度保持响应式卡片图像的纵横比?