在 R 中使用 Lookup Table 匹配区间
Matching Intervals with Using Lookup Table in R
我希望使用具有符合标准(即“较差”、“平均”等)的开始和结束间隔的查找参考 table
我有一个数据 table,我想在其中创建一个新的标准列,根据数据值在查找 table 中所处的时间间隔来标记数据值。下面是一个简化的例子。我的实际数据集要大得多并且需要是动态的,所以我不必硬编码或在脚本中创建许多单独的对象。
lookup_df = data.frame("Standard" = c("Poor", "Below_Average", "Average", "Above_Average", "Good"),
"Start" = c(2,3,4,5,6), "End" = c(3,4,5,6,7))
col = c(1.5, 5.2, 4.1, 3.3, 9.6, 2.4)
我正在尝试使用 ifelse() 和 findInterval() return 来自查找标准列的索引。我知道问题是索引部分,因为 findInterval returns 0s 不能被索引。我试图通过向 findInterval 添加 +1 来解决这个问题,但这也没有用。这是我一直在尝试的:
ifelse(findInterval(col, lookup_df$End)+1 > 1, lookup_df$Standard[findInterval(col, lookup_df$End)+1], "Poor")
# [1] "Poor" "Above_Average" "Average" "Below_Average"
# [5] NA "Poor"
我想要的结果是:
# [1] "Poor" "Above_Average" "Average" "Below_Average"
# [5] "Good" "Poor"
我已尝试使用此示例中的 transform() ,但也无法使其正常运行。
ifelse() 索引问题似乎与此一致
我猜我缺少一个简单的解决方案!感谢任何帮助。
编辑以包含最终答案
这是我基于 R. Lima 的解决方案合并到 dplyr 中使用的最终解决方案:
lookup_vec = as.character(lookup_df$Standard)
names(lookup_vec) <- c("0", "1", "2", "3","4")
df = data.frame(col = c(1.5, 5.2, 4.1, 3.3, 9.6, 2.4))
df = df %>%
mutate(Standard = stringr::str_replace_all(
findInterval(col, lookup_df$Start[-1]), lookup_vec))
这应该可以做到,尽管我使用了包 stringr
中的 str_replace_all() 而不是 ifelse()。这个函数处理你提到的零问题。
可能有一种更优雅、更快捷的方法,但这个方法可以解决问题。
# Defining the lookup reference object
lookup <- c("Poor", "Below_Average", "Average", "Above_Average", "Good")
names(lookup) <- c("0", "1", "2", "3","4")
# Defining your data frame
df <- data.frame(col = c(1.5, 5.2, 4.1, 3.3, 9.6, 2.4))
# Classifying the data and inserting into your data frame
df$classes <- stringr::str_replace_all(
findInterval(df$col, c(3,4,5,6)), lookup)
df$classes
[1] "Poor" "Above_Average" "Average" "Below_Average" "Good"
[6] "Poor"
我希望使用具有符合标准(即“较差”、“平均”等)的开始和结束间隔的查找参考 table
我有一个数据 table,我想在其中创建一个新的标准列,根据数据值在查找 table 中所处的时间间隔来标记数据值。下面是一个简化的例子。我的实际数据集要大得多并且需要是动态的,所以我不必硬编码或在脚本中创建许多单独的对象。
lookup_df = data.frame("Standard" = c("Poor", "Below_Average", "Average", "Above_Average", "Good"),
"Start" = c(2,3,4,5,6), "End" = c(3,4,5,6,7))
col = c(1.5, 5.2, 4.1, 3.3, 9.6, 2.4)
我正在尝试使用 ifelse() 和 findInterval() return 来自查找标准列的索引。我知道问题是索引部分,因为 findInterval returns 0s 不能被索引。我试图通过向 findInterval 添加 +1 来解决这个问题,但这也没有用。这是我一直在尝试的:
ifelse(findInterval(col, lookup_df$End)+1 > 1, lookup_df$Standard[findInterval(col, lookup_df$End)+1], "Poor")
# [1] "Poor" "Above_Average" "Average" "Below_Average"
# [5] NA "Poor"
我想要的结果是:
# [1] "Poor" "Above_Average" "Average" "Below_Average"
# [5] "Good" "Poor"
我已尝试使用此示例中的 transform()
ifelse() 索引问题似乎与此一致
我猜我缺少一个简单的解决方案!感谢任何帮助。
编辑以包含最终答案
这是我基于 R. Lima 的解决方案合并到 dplyr 中使用的最终解决方案:
lookup_vec = as.character(lookup_df$Standard)
names(lookup_vec) <- c("0", "1", "2", "3","4")
df = data.frame(col = c(1.5, 5.2, 4.1, 3.3, 9.6, 2.4))
df = df %>%
mutate(Standard = stringr::str_replace_all(
findInterval(col, lookup_df$Start[-1]), lookup_vec))
这应该可以做到,尽管我使用了包 stringr
中的 str_replace_all() 而不是 ifelse()。这个函数处理你提到的零问题。
可能有一种更优雅、更快捷的方法,但这个方法可以解决问题。
# Defining the lookup reference object
lookup <- c("Poor", "Below_Average", "Average", "Above_Average", "Good")
names(lookup) <- c("0", "1", "2", "3","4")
# Defining your data frame
df <- data.frame(col = c(1.5, 5.2, 4.1, 3.3, 9.6, 2.4))
# Classifying the data and inserting into your data frame
df$classes <- stringr::str_replace_all(
findInterval(df$col, c(3,4,5,6)), lookup)
df$classes
[1] "Poor" "Above_Average" "Average" "Below_Average" "Good"
[6] "Poor"