Lar*_*Cai 1 r dataframe tibble data-wrangling
考虑 2 个 dfs:
df1:
| 可乐 | 上校 B | 上校 |
|---|---|---|
| 汤姆 | 冰淇淋 | 0.2 |
| 汤姆 | 糖果 | 0.4 |
| 汤姆 | 棒糖 | 0.6 |
| 鲍勃 | 糖果 | 0.1 |
| 安倍 | 糖果 | 0.1 |
df2:
| 可乐 | 寒冷的 | 科尔 |
|---|---|---|
| 汤姆 | 糖果 | 0.5 |
| 汤姆 | 巧克力 | 0.2 |
| 汤姆 | 可乐 | 0.3 |
如果我使用full_join,right_join或mergewith by = "Col A"(with all.y=TRUE),我会将每个“排列”作为自己的行:
df3:
| 可乐 | 上校 B | 上校 | 寒冷的 | 科尔 |
|---|---|---|---|---|
| 汤姆 | 冰淇淋 | 0.2 | 糖果 | 0.5 |
| 汤姆 | 冰淇淋 | 0.2 | 巧克力 | 0.2 |
| 汤姆 | 冰淇淋 | 0.2 | 可乐 | 0.3 |
| 汤姆 | 糖果 | 0.4 | 糖果 | 0.5 |
| 汤姆 | 糖果 | 0.4 | 巧克力 | 0.2 |
| 汤姆 | 糖果 | 0.4 | 可乐 | 0.3 |
| 汤姆 | 棒糖 | 0.6 | 糖果 | 0.5 |
| 汤姆 | 棒糖 | 0.6 | 巧克力 | 0.2 |
| 汤姆 | 棒糖 | 0.6 | 可乐 | 0.3 |
| 鲍勃 | 糖果 | 0.1 | 不适用 | 不适用 |
| 安倍 | 糖果 | 0.1 | 不适用 | 不适用 |
如果我使用inner_join, left_join, 或mergewith by = "Col A"(没有all.y=TRUE ),除了子集化为仅操作的行之外,我得到的结果与上面相同,例如,将删除包含 Abe 和 Bob 的行:
df4:
| 可乐 | 上校 B | 上校 | 寒冷的 | 科尔 |
|---|---|---|---|---|
| 汤姆 | 冰淇淋 | 0.2 | 糖果 | 0.5 |
| 汤姆 | 冰淇淋 | 0.2 | 巧克力 | 0.2 |
| 汤姆 | 冰淇淋 | 0.2 | 可乐 | 0.3 |
| 汤姆 | 糖果 | 0.4 | 糖果 | 0.5 |
| 汤姆 | 糖果 | 0.4 | 巧克力 | 0.2 |
| 汤姆 | 糖果 | 0.4 | 可乐 | 0.3 |
| 汤姆 | 棒糖 | 0.6 | 糖果 | 0.5 |
| 汤姆 | 棒糖 | 0.6 | 巧克力 | 0.2 |
| 汤姆 | 棒糖 | 0.6 | 可乐 | 0.3 |
我试图在不增加行数的情况下进行合并,因为唯一的排列并不重要。他们加入的顺序也无关紧要。预期输出:
df5:
| 可乐 | 上校 B | 上校 | 寒冷的 | 科尔 |
|---|---|---|---|---|
| 汤姆 | 冰淇淋 | 0.2 | 糖果 | 0.5 |
| 汤姆 | 糖果 | 0.4 | 巧克力 | 0.2 |
| 汤姆 | 棒糖 | 0.6 | 可乐 | 0.3 |
| 鲍勃 | 糖果 | 0.1 | 不适用 | 不适用 |
| 安倍 | 糖果 | 0.1 | 不适用 | 不适用 |
过滤 df3 byunique无济于事,因为排列确实是独一无二的。
在我的场景中,我 100% 确定每个后续 df 加入到 df1 正好有 3 行,这与df1$'Col A'.
在我的真实场景中,这个加入/合并将部署在一个循环中,其中每个条目Col A也恰好出现 3 次。所以在后面的循环中,它会对“Abe”和“Bob”做同样的事情。
bind_cols()不够通用,因为列可能已经在前一个循环中创建(即Col D并且Col E已经由 Tom 的循环创建,N/As 代表 Abe 和 Bob 的行)。在这种情况下,我只希望估算值,而不是创建新列(这会因具有相同的列名而进一步冲突)。
是否有脚本/函数/包来执行我的意图?转换为 tibbles 也很好。也许是将 a _join/merge与 a结合的一些条件bind_cols?
问题是*_join不知道要加入哪一行,所以它加入了所有三行。给定您的预期输出,您希望Tom行以它们在数据框中出现的相同顺序加入。您可以添加rowid列,这将让*_join知道你想加入Tom/1到Tom/1。
library(tidyverse)
# data
df1 <- read.table(text = "
ColA ColB ColC
Tom IceCream 0.2
Tom Candy 0.4
Tom Lollipop 0.6
Bob Sweets 0.1
Abe Sweets 0.1", h = T)
df2 <- read.table(text = "
ColA ColD ColE
Tom Sweets 0.5
Tom Chocolate 0.2
Tom Cola 0.3", h = T)
# add row ids
df1 <- df1 %>%
group_by(ColA) %>%
mutate(rowid = row_number())
df2 <- df2 %>%
mutate(rowid = row_number())
# join
left_join(df1,df2)
#> Joining, by = c("ColA", "rowid")
#> # A tibble: 5 x 6
#> # Groups: ColA [3]
#> ColA ColB ColC rowid ColD ColE
#> <chr> <chr> <dbl> <int> <chr> <dbl>
#> 1 Tom IceCream 0.2 1 Sweets 0.5
#> 2 Tom Candy 0.4 2 Chocolate 0.2
#> 3 Tom Lollipop 0.6 3 Cola 0.3
#> 4 Bob Sweets 0.1 1 <NA> NA
#> 5 Abe Sweets 0.1 1 <NA> NA
Run Code Online (Sandbox Code Playgroud)
由reprex 包( v2.0.0 )于 2021 年 8 月 31 日创建
分配rowids的另一种方法是df1基于ColA,运行cbind/ 的子集bind_cols,然后重新加入df1。
df1 %>%
filter(ColA == unique(df2$ColA)) %>%
bind_cols(df2[,-1]) %>%
right_join(df1)
#-----------
Joining, by = c("ColA", "ColB", "ColC")
ColA ColB ColC ColD ColE
1 Tom IceCream 0.2 Sweets 0.5
2 Tom Candy 0.4 Chocolate 0.2
3 Tom Lollipop 0.6 Cola 0.3
4 Bob Sweets 0.1 <NA> NA
5 Abe Sweets 0.1 <NA> NA
Run Code Online (Sandbox Code Playgroud)