r - 使用 tidyverse 环境循环遍历数据帧,比较结果,并返回一个值。类似于excel中的vlookup功能
问题描述
不过,要说清楚。假设我有一个包含很多结果(f1、f2、f3 等)的数据框和另一个数据框,其中我对这些结果(f1、f2、f3)有一个“规范表”(在心理学中很常见) . 我需要将第一个数据帧中的结果与第二个数据帧中的结果进行比较,然后返回相应的“百分位数”和“分类”。然后,我需要继续对第一个数据帧中的所有其他变量执行此过程。
重要提示:假设我的值是 30,这个结果有两个百分位数(比如说 0.5 和 0.55),我需要保持最高的百分位数,因此是最高的分类。
我想留在 tidyverse 环境中。太感谢了!
那是代码:
normative_table <- structure(list(classification = c("Muito inferior", "inferior",
"medio inferior", "medio inferior", "medio inferior", "medio inferior",
"medio", "medio", "medio", "medio", "medio", "medio", "medio",
"medio", "medio", "medio superior", "medio superior", "medio superior",
"medio superior", "Superior", "Muito superior"), percentile = c(0,
0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55,
0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1), f1 = c(`0%` = 1,
`5%` = 1.1, `10%` = 1.3, `15%` = 1.4, `20%` = 1.4, `25%` = 1.5,
`30%` = 1.6, `35%` = 1.6, `40%` = 1.7, `45%` = 1.8, `50%` = 1.9,
`55%` = 1.9, `60%` = 2, `65%` = 2.1, `70%` = 2.3, `75%` = 2.5,
`80%` = 2.7, `85%` = 2.9, `90%` = 3.1, `95%` = 3.4, `100%` = 4.6
), f2 = c(`0%` = 1, `5%` = 1.12, `10%` = 1.25, `15%` = 1.38,
`20%` = 1.5, `25%` = 1.62, `30%` = 1.62, `35%` = 1.75, `40%` = 1.75,
`45%` = 1.88, `50%` = 1.88, `55%` = 2, `60%` = 2, `65%` = 2.12,
`70%` = 2.25, `75%` = 2.38, `80%` = 2.5, `85%` = 2.62, `90%` = 3,
`95%` = 3.25, `100%` = 4.25), f3 = c(`0%` = 1, `5%` = 1.17, `10%` = 1.33,
`15%` = 1.5, `20%` = 1.67, `25%` = 1.83, `30%` = 1.83, `35%` = 2,
`40%` = 2.17, `45%` = 2.17, `50%` = 2.33, `55%` = 2.5, `60%` = 2.67,
`65%` = 2.67, `70%` = 2.83, `75%` = 2.83, `80%` = 3, `85%` = 3.17,
`90%` = 3.33, `95%` = 3.67, `100%` = 4.67)), row.names = c(NA,
-21L), class = "data.frame")
items <- structure(list(id = c("1", "2", "3", "4", "5", "6", "7", "8",
"9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
"20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30",
"31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41",
"42", "43", "44", "45", "46", "47", "48", "49", "50", "51", "52",
"53", "54", "55", "56", "57", "58", "59", "60", "61", "62", "63",
"64", "65", "66", "67", "68", "69", "70", "71", "72", "73", "74",
"75", "76", "77", "78", "79", "80", "81", "82", "83", "84", "85",
"86", "87", "88", "89", "90", "91", "92", "93", "94", "95", "96",
"97", "98", "99", "100"), f1 = c(1.1, 1.5, 1.3, 1.4, 1.9, 2,
2.5, 2.3, 2.2, NA, 1.9, 2, 2.7, 1.3, 2.9, 2.6, 1.9, 3, 1.6, 1.2,
1.6, NA, 1.9, 2.2, 2.3, 4.4, 1.6, 1.2, 3.9, 2.7, 1.5, 2.2, 1.9,
2, 1.5, 1.4, 3.1, 2.5, 1.1, 1.1, 1.2, NA, 1.5, 1.7, 2.8, 2.2,
1.7, 1.8, 1.1, 3, 1.4, 2.8, 1.4, 1.9, 3.9, 2, 4.6, 2, 1.7, 1.7,
2.5, 1.5, 3.3, 3.4, 1.6, 1.9, 2.5, 1.2, 1.4, 1.9, 2.5, 1.3, 2,
1.4, 1.4, 3.4, 1.6, 1.7, 2.6, 2.8, 1.6, 3, 3, 1.5, 1.6, 1.8,
1.9, 2.8, 1.5, 1.9, 1.9, 1, 1.2, 2.7, 1.9, 1.9, 1.7, 3, 1.5,
3.7), f2 = c(1.875, 1.625, 2.5, 1.875, 1.875, 1.375, 1.625, 1.125,
2.625, NA, 1.875, 1.125, 1.5, 1.625, 1.125, 1.125, 2, 3.875,
2.5, 1.875, 1.5, NA, 1.875, 1.625, 2.625, 2, 1.25, 2.25, 2.625,
2, 3.625, 2, 1.75, 2.25, 1.875, 2.5, 3.25, 1.125, 2, 3, 1.75,
NA, 2.125, 1.5, 2.5, 1.625, 2.25, 1.75, 2.875, 1.375, 2.75, 2.25,
1.5, 1.625, 2.625, 1.5, 2.375, 2.25, 1.125, 1.875, 2.75, 1.625,
3.125, 1.25, 2.125, 1.25, 1.875, 2.375, 1.25, 1.75, 2.875, 2.5,
2.25, 2, 2, 1.25, 2.375, 1.5, 1.5, 3.5, 2, 1.375, 1.375, 2, 2.25,
2.5, 2.375, 2.625, 2, 1.125, 1.375, 3.5, 2.25, 3, 1.5, 1.5, 2.625,
1.375, 2.75, 2.375), f3 = c(1.16666666666667, 1.33333333333333,
1.5, 1.16666666666667, 1.66666666666667, 3, 3.16666666666667,
2, 2.5, NA, 2.16666666666667, 3.16666666666667, 2.83333333333333,
1, 1.5, 3.66666666666667, 3, 3, 2.66666666666667, 1.16666666666667,
2.33333333333333, NA, 2.16666666666667, 1.66666666666667, 1.83333333333333,
2.5, 2.66666666666667, 2.66666666666667, 3.66666666666667, 3.16666666666667,
2.66666666666667, 1.16666666666667, 3, 2.5, 1.66666666666667,
3.66666666666667, 1.83333333333333, 3, 2.33333333333333, 1.33333333333333,
1.83333333333333, NA, 1.5, 1.66666666666667, 2.66666666666667,
1.66666666666667, 2.16666666666667, 1.66666666666667, 1.33333333333333,
2.16666666666667, 1, 2.5, 1.66666666666667, 2, 3.66666666666667,
3.66666666666667, 2.33333333333333, 2.16666666666667, 1, 2.16666666666667,
3, 1.33333333333333, 3, 2.16666666666667, 2.66666666666667, 2.16666666666667,
4.33333333333333, 2, 1.16666666666667, 3.33333333333333, 1.83333333333333,
1.5, 2.16666666666667, 3, 3, 2.16666666666667, 2.83333333333333,
1.66666666666667, 2.5, 3.16666666666667, 1.33333333333333, 4.66666666666667,
2.16666666666667, 3, 2, 1.5, 1.83333333333333, 3.66666666666667,
3, 3.5, 2.16666666666667, 1.66666666666667, 2.66666666666667,
4.5, 3, 2.5, 1.33333333333333, 2.16666666666667, 2.66666666666667,
3.5)), row.names = c(NA, -100L), class = "data.frame")
解决方案
library(purrr) # for map() and reduce()
library(stringr) # for str_replace()
library(dplyr) # for select(), left_join(), group_by(), summarise(), ungroup(), mutate_at(), arrange()
# first define the function `fct()` that does the job for one value of "f":
fct <- function(x) {
items %>%
select(id, x) %>%
left_join(normative_table, x) %>%
select(id, percentile, classification) %>%
group_by(id, classification) %>%
summarise(percentile = max(percentile)) %>%
ungroup() %>%
mutate_at("id", as.integer) %>%
arrange(id) %>%
mutate_at("id", as.character)
}
# then use it for your need:
map(c("f1", "f2", "f3"), f) %>%
reduce(left_join, "id") %>%
setNames(., names(.) %>%
str_replace("\\.x", "1") %>%
str_replace("\\.y", "2") %>%
str_replace("([en])$", "\\13")) %>%
left_join(items, .)
您可能可以将map()
and替换reduce()
为map_dfc()
.
推荐阅读
- mysql - MySQL 联合表 SUM 和额外子句
- python - 使用 python 和 selenium 在元素内部搜索另一个元素
- r - 减少 R 中的数据集 - 过滤和分组?
- javascript - 如何构建这个简单的正则表达式?
- laravel - Laravel 5.8 - Auth::user() 具有不同的警卫
- python - 字母的 XML ParseError?
- c# - C# 在 SqlHelper.DB 中使用参数
- c++ - 为什么我的代码不能正确计算利息?
- java - 我如何通过 ssh spring shell cli 访问
- java - 将 PNG 转换为位图到 Byte[] 以存储在 SQL 中