如何在R中基于另一个数据框的条件生成新数据框?
基于两个数据框的条件映射生成新数据框
数据定义
用户提供的两个数据框定义如下:
df1 <- data.frame(Q1 = rep(c(0, 1), 3), Q2 = rep(c(1, 0), 3), Q3 = rep(1, 6)) df2 <- data.frame(Q1 = rep(c(0, 1, 2), 2), Q2 = rep(c(2, 1, 0), 2), Q3 = c(rep(1, 3), rep(2, 3)))
输出结果:
> df1 Q1 Q2 Q3 1 0 1 1 2 1 0 1 3 0 1 1 4 1 0 1 5 0 1 1 6 1 0 1 > df2 Q1 Q2 Q3 1 0 2 1 2 1 1 1 3 2 0 1 4 0 2 2 5 1 1 2 6 2 0 2
需求
需要生成新数据框df3,每个元素根据以下规则映射:
| 新元素值 | 条件 |
|---|---|
| 6 | df1 == 1 & df2 == 2 |
| 5 | df1 == 1 & df2 == 1 |
| 4 | df1 == 1 & df2 == 0 |
| 3 | df1 == 0 & df2 == 0 |
| 2 | df1 == 0 & df2 == 1 |
| 1 | df1 == 0 & df2 == 2 |
用户的错误尝试
用户尝试用modify函数,但索引逻辑错误,导致代码无法运行:
df3 <- modify(df1, function(x) ifelse(x == 1 & df2[x] == 2, 6, ifelse(x == 1 & df2[x] == 1, 5, ifelse(x == 1 & df2[x] == 0, 4, ifelse(x == 0 & df2[x] == 0, 3, ifelse(x == 0 & df2[x] == 1, 2, 1))))))
解决方案
方法1:向量化ifelse嵌套(直接对应条件)
数据框维度一致,可直接进行元素级比较,无需逐列遍历索引:
df3 <- ifelse(df1 == 1 & df2 == 2, 6, ifelse(df1 == 1 & df2 == 1, 5, ifelse(df1 == 1 & df2 == 0, 4, ifelse(df1 == 0 & df2 == 0, 3, ifelse(df1 == 0 & df2 == 1, 2, 1))))) # 转换为数据框保持结构一致 df3 <- as.data.frame(df3)
运行结果:
> df3 Q1 Q2 Q3 1 3 6 5 2 5 3 5 3 1 4 5 4 3 6 5 5 5 3 5 6 1 4 5
方法2:dplyr + case_when(可读性更强)
用tidyverse语法的case_when让条件逻辑更清晰:
library(dplyr) df3 <- df1 %>% mutate_all(~ case_when( .x == 1 & df2[[cur_column()]] == 2 ~ 6, .x == 1 & df2[[cur_column()]] == 1 ~ 5, .x == 1 & df2[[cur_column()]] == 0 ~ 4, .x == 0 & df2[[cur_column()]] == 0 ~ 3, .x == 0 & df2[[cur_column()]] == 1 ~ 2, TRUE ~ 1 ))
方法3:映射矩阵(高效易维护)
先构建映射关系矩阵,通过元素组合直接索引取值:
# 行对应df1的值(0,1),列对应df2的值(0,1,2) map_matrix <- matrix(c(3,2,1, 4,5,6), nrow=2, byrow=TRUE, dimnames = list(c("0","1"), c("0","1","2"))) # 元素级索引并转换为数据框 df3 <- as.data.frame(matrix(map_matrix[cbind(as.character(df1), as.character(df2))], nrow = nrow(df1))) colnames(df3) <- colnames(df1)
内容的提问来源于stack exchange,提问作者user20291515
相关产品推荐
相关产品推荐

