【问题标题】:Use case_when function of dplyr with connection between two datasets使用 dplyr 的 case_when 函数与两个数据集之间的连接
【发布时间】:2026-01-26 03:35:01
【问题描述】:

我有以下两个示例数据集,并希望使用 case_when 函数作为两个数据集的组合:

game_data <- data.frame(player = c(1,1,1,2,2,2,3,3,3), level = c(1,2,3,1,2,3,1,2,3), score=c(0,150,170,80,100,110,75,100,0))
> game_data
  player level score
1      1     1     0
2      1     2   150
3      1     3   170
4      2     1    80
5      2     2   100
6      2     3   110
7      3     1    75
8      3     2   100
9      3     3     0
> 
> range_data <- data.frame(level = c(1,2,3), Point1 = c(20,70,140), Point2 = c(40,80,180), Point3 = c(60,90,220))
> range_data
  level Point1 Point2 Point3
1     1     20     40     60
2     2     70     80     90
3     3    140    180    220
> 

我现在想使用第二个数据集中的点之间的范围来根据得分之间的范围在 game_data 数据集中创建一个新变量。 例如,如果用户 1 的分数为 150 处于级别 2,则新变量 PointRange 应显示“Range4”,因为它高于 90。

我尝试了以下方法,但它不起作用:

result <- game_data %>%
  mutate(PointRange = case_when(level == range_data$level & score <  range_data$point1 ~ "Range1",
                                level == range_data$level & score >= range_data$point1 & score < data$point2 ~ "Range2",
                                level == range_data$level & score >= range_data$point2 & score <= data$point3 ~ "Range3",
                                level == range_data$level & score >= range_data$point3 ~ "Range4"))

我该如何管理?提前致谢!

【问题讨论】:

    标签: r data-structures case-when dplyr


    【解决方案1】:

    由于您在级别列上进行匹配,您可以简单地 inner_join 该列,然后从单个数据框工作。

    参数是按顺序计算的,所以你必须从最具体的到最一般的。

    game_data %>%
      inner_join(range_data, by = "level") %>%
      mutate(PointRange = case_when(score>=Point3 ~ "Range4",
                                    score>=Point2 ~"Range3",
                                    score>=Point1 ~"Range2",
                                    score<Point1 ~"Range1")) %>%
      select(-Point1,-Point2,-Point3)
    
    #  player level score PointRange
    #1      1     1     0     Range1
    #2      1     2   150     Range4
    #3      1     3   170     Range2
    #4      2     1    80     Range4
    #5      2     2   100     Range4
    #6      2     3   110     Range1
    #7      3     1    75     Range4
    #8      3     2   100     Range4
    #9      3     3     0     Range1
    

    【讨论】:

    • 我认为这个答案已被删除,因此我发布了我的答案。那我删掉我的吧。
    • 由于范围的顺序相反,我不得不更改 case_when 的顺序。原来这导致结果不正确
    • 是的,我注意到了。您可以更明确一点,即 (score &gt;= Point1 &amp; score &lt; Point2)(score &gt;= Point2 &amp; score &lt; Point3) 用于两个中间分数
    • 这很好用,非常感谢!我也利用了你推荐的Sotos,非常感谢。