我有两个示例数据集:
data <- data.frame(
ID = c(1:10)
, COL1 = LETTERS[1:10]
, COL2 = letters[1:10]
, COL3 = as.character(10:1)
, stringsAsFactors = FALSE
)
match <- data.frame(
COL1 = c("A", "C", "F", "*", "F")
, COL2 = c("a", "c", "*", "*", "*")
, COL3 = c("10", "8", "5", "*", "*")
, VAL = c(0.8, 0.7, 0.9, 0.85, 0.1)
, stringsAsFactors = FALSE
)
他们看起来像:
> data
ID COL1 COL2 COL3
1 1 A a 10
2 2 B b 9
3 3 C c 8
4 4 D d 7
5 5 E e 6
6 6 F f 5
7 7 G g 4
8 8 H h 3
9 9 I i 2
10 10 J j 1
> match
COL1 COL2 COL3 VAL
1 A a 10 0.80
2 C c 8 0.70
3 F * 5 0.90
4 * * * 0.85
5 F * * 0.10
结果表应该将
data
表与match
结合起来 表,以便match
表中的信息最适合data
表中的行。所以,如果你看看比赛表,那里 是COL1
中F的两个不同匹配。因为还有一个5英寸COL3
,值0.9应该加入。
结果如下:
ID COL1 COL2 COL3 VAL
1 1 A a 10 0.80
2 2 B b 9 0.85
3 3 C c 8 0.70
4 4 D d 7 0.85
5 5 E e 6 0.85
6 6 F f 5 0.90
7 7 G g 4 0.85
8 8 H h 3 0.85
9 9 I i 2 0.85
10 10 J j 1 0.85
我为此写了一个解决方法:
library(tidyverse)
col1u <- sort(unique(match$COL1))
col2u <- sort(unique(match$COL2))
col3u <- sort(unique(match$COL3))
dataTransformed <- data %>%
mutate(COL1 = ifelse(COL1 %in% col1u, COL1, "*")
, COL2 = ifelse(COL2 %in% col2u, COL2, "*")
, COL3 = ifelse(COL3 %in% col3u, COL3, "*"))
dataJoin <- inner_join(dataTransformed, match)
这很好但我不知道这种方法是否过于复杂,因为真正的数据集有更多的列。有更简单的解决方案吗?
答案 0 :(得分:0)
我们可以做到
library(tidyverse)
match %>%
summarise_at(vars(matches("COL")), funs(list(sort(unique(.))))) %>%
map2_df(data[names(.)], ., ~ case_when(.x %in% .y[[1]] ~ .x, TRUE ~ "*") ) %>%
bind_cols(data['ID'], .) %>%
inner_join(match)