合并单元格不匹配的两个数据帧
Merge two data frames with cell mismatches
我目前被困住了:我已经抓取了一个网站,该网站为同一产品指定了非常不同的名称(即同一产品可能被列为“1”、"Number 1"、"Category 3 - Number 1")。对于这些值中的每一个,我想分配一个不同的结果(从具有更好名称的不同站点中删除)。
# Messy code from original website:
df1 <- data.frame(c(1,1,1,1,2,2,2,3,3,3,3,3,4,4,4), c("Number 1", "Number 2",
"Category 1", "3", "8",
"Number 2 - Category 5","1", "Number 4",
"Kat 1", "4", "Kat 2",
"Number5", "Test", "4","3"))
colnames(df1) <- c("ID", "Category")
> df1
ID Category
1 1 Number 1
2 1 Number 2
3 1 Category 1
4 1 3
5 2 8
6 2 Number 2 - Category 5
7 2 1
8 3 Number 4
9 3 Kat 1
10 3 4
11 3 Kat 2
12 3 Number5
13 4 Test
14 4 4
15 4 3
# Code from other site:
df2 <- data.frame(c(1,1,1,1,2,2,2,2,3,3,3,3,3,4,4,4,4,4), c("1", "2", "3", "Category 1",
"Category 5", "1", "2", "3", "4",
"Kat 1", "Kat 2", "Kat 3","5",
"1","2","3","4","Test"),
c(1,2,3,4,5,6,5,8,9,10,11,12,13,14,15,16,17,18))
colnames(df2) <- c("ID", "Category", "Outcome")
> df2
ID Category Outcome
1 1 1 1
2 1 2 2
3 1 3 3
4 1 Category 1 4
5 2 Category 5 5
6 2 1 6
7 2 2 5
8 2 3 8
9 3 4 9
10 3 Kat 1 10
11 3 Kat 2 11
12 3 Kat 3 12
13 3 5 13
14 4 1 14
15 4 2 15
16 4 3 16
17 4 4 17
18 4 Test 18
我想保留数据框 1,但分配取自 df2 的 "Output",与 ID 和类别相匹配。这可以通过左连接轻松完成,但如您所见,类别级别并不相同。
我一直在考虑重命名关卡,但考虑到我的数据集的大小(约 500,000 行),这似乎不可行,我希望有一个更简单的(grepl、gsub?)解决方案。
我的最终结果应该是这样的:
> df1
ID Category Outcome
1 1 Number 1 1
2 1 Number 2 2
3 1 Category 1 4
4 1 3 3
5 2 8 NA
6 2 Number 2 - Category 5 5
7 2 1 6
8 3 Number 4 9
9 3 Kat 1 10
10 3 4 9
11 3 Kat 2 11
12 3 Number5 13
13 4 Test 18
14 4 4 17
15 4 3 16
对于复杂的示例,我深表歉意,我想确保涵盖所有意外情况。这里再解释一下:
每当它有一个类别时,通常都会以正确的拼写完整列出(即 "Kat" 总是出现 "Kat" 而 "Category" 总是出现"Category")。数字可能会在前面出现单词 "Number" 或仅作为数字本身出现。如果没有出现数字,我希望它显示 NA - 稍后我将不得不手动添加缺失的数字。
非常感谢您的阅读 - 非常感谢您的帮助!
这可能会大大简化,但您可以尝试:
library(dplyr)
extr_last_digit <- function(x) substring(x, first = regexpr("(\d+)(?!.*\d)", x, perl = T))
extr_cat_digit <- function(x) gsub(".*((?<=Category\s)\d+).*|.*((?<=Kat\s)\d+).*", "\1\2", x, perl = T)
df1 %>%
mutate(
join = case_when(
!grepl("Category|Kat", Category) ~ extr_last_digit(Category),
TRUE ~ paste0("Category ", extr_cat_digit(Category)))
) %>%
left_join(df2 %>%
mutate(
join = case_when(
!grepl("Category|Kat", Category) ~ extr_last_digit(Category),
TRUE ~ paste0("Category ", extr_cat_digit(Category))
),
Category = NULL),
by = c("ID", "join")
) %>%
select(-join)
输出:
ID Category Outcome
1 1 Number 1 1
2 1 Number 2 2
3 1 Category 1 4
4 1 3 3
5 2 8 NA
6 2 Number 2 - Category 5 5
7 2 1 6
8 3 Number 4 9
9 3 Kat 1 10
10 3 4 9
11 3 Kat 2 11
12 3 Number5 13
13 4 Test 18
14 4 4 17
15 4 3 16
基本上,它的作用是在具有相同结构的 df
中创建一个 join
列 - 如果它没有找到任何提及 Category
或 Kat
,它使用最后提到的数字进行合并,否则它会粘贴单词 Category
和单词 Category
或 Kat
.
之后提到的数字
这也适用于单词 Test
,因为如果找不到任何数字,它就使用整个字符串。
我目前被困住了:我已经抓取了一个网站,该网站为同一产品指定了非常不同的名称(即同一产品可能被列为“1”、"Number 1"、"Category 3 - Number 1")。对于这些值中的每一个,我想分配一个不同的结果(从具有更好名称的不同站点中删除)。
# Messy code from original website:
df1 <- data.frame(c(1,1,1,1,2,2,2,3,3,3,3,3,4,4,4), c("Number 1", "Number 2",
"Category 1", "3", "8",
"Number 2 - Category 5","1", "Number 4",
"Kat 1", "4", "Kat 2",
"Number5", "Test", "4","3"))
colnames(df1) <- c("ID", "Category")
> df1
ID Category
1 1 Number 1
2 1 Number 2
3 1 Category 1
4 1 3
5 2 8
6 2 Number 2 - Category 5
7 2 1
8 3 Number 4
9 3 Kat 1
10 3 4
11 3 Kat 2
12 3 Number5
13 4 Test
14 4 4
15 4 3
# Code from other site:
df2 <- data.frame(c(1,1,1,1,2,2,2,2,3,3,3,3,3,4,4,4,4,4), c("1", "2", "3", "Category 1",
"Category 5", "1", "2", "3", "4",
"Kat 1", "Kat 2", "Kat 3","5",
"1","2","3","4","Test"),
c(1,2,3,4,5,6,5,8,9,10,11,12,13,14,15,16,17,18))
colnames(df2) <- c("ID", "Category", "Outcome")
> df2
ID Category Outcome
1 1 1 1
2 1 2 2
3 1 3 3
4 1 Category 1 4
5 2 Category 5 5
6 2 1 6
7 2 2 5
8 2 3 8
9 3 4 9
10 3 Kat 1 10
11 3 Kat 2 11
12 3 Kat 3 12
13 3 5 13
14 4 1 14
15 4 2 15
16 4 3 16
17 4 4 17
18 4 Test 18
我想保留数据框 1,但分配取自 df2 的 "Output",与 ID 和类别相匹配。这可以通过左连接轻松完成,但如您所见,类别级别并不相同。
我一直在考虑重命名关卡,但考虑到我的数据集的大小(约 500,000 行),这似乎不可行,我希望有一个更简单的(grepl、gsub?)解决方案。
我的最终结果应该是这样的:
> df1
ID Category Outcome
1 1 Number 1 1
2 1 Number 2 2
3 1 Category 1 4
4 1 3 3
5 2 8 NA
6 2 Number 2 - Category 5 5
7 2 1 6
8 3 Number 4 9
9 3 Kat 1 10
10 3 4 9
11 3 Kat 2 11
12 3 Number5 13
13 4 Test 18
14 4 4 17
15 4 3 16
对于复杂的示例,我深表歉意,我想确保涵盖所有意外情况。这里再解释一下:
每当它有一个类别时,通常都会以正确的拼写完整列出(即 "Kat" 总是出现 "Kat" 而 "Category" 总是出现"Category")。数字可能会在前面出现单词 "Number" 或仅作为数字本身出现。如果没有出现数字,我希望它显示 NA - 稍后我将不得不手动添加缺失的数字。
非常感谢您的阅读 - 非常感谢您的帮助!
这可能会大大简化,但您可以尝试:
library(dplyr)
extr_last_digit <- function(x) substring(x, first = regexpr("(\d+)(?!.*\d)", x, perl = T))
extr_cat_digit <- function(x) gsub(".*((?<=Category\s)\d+).*|.*((?<=Kat\s)\d+).*", "\1\2", x, perl = T)
df1 %>%
mutate(
join = case_when(
!grepl("Category|Kat", Category) ~ extr_last_digit(Category),
TRUE ~ paste0("Category ", extr_cat_digit(Category)))
) %>%
left_join(df2 %>%
mutate(
join = case_when(
!grepl("Category|Kat", Category) ~ extr_last_digit(Category),
TRUE ~ paste0("Category ", extr_cat_digit(Category))
),
Category = NULL),
by = c("ID", "join")
) %>%
select(-join)
输出:
ID Category Outcome
1 1 Number 1 1
2 1 Number 2 2
3 1 Category 1 4
4 1 3 3
5 2 8 NA
6 2 Number 2 - Category 5 5
7 2 1 6
8 3 Number 4 9
9 3 Kat 1 10
10 3 4 9
11 3 Kat 2 11
12 3 Number5 13
13 4 Test 18
14 4 4 17
15 4 3 16
基本上,它的作用是在具有相同结构的 df
中创建一个 join
列 - 如果它没有找到任何提及 Category
或 Kat
,它使用最后提到的数字进行合并,否则它会粘贴单词 Category
和单词 Category
或 Kat
.
这也适用于单词 Test
,因为如果找不到任何数字,它就使用整个字符串。