我有~16个.txt文件,我需要把它变成一个宽平面文件。对于每个新文件,时间已过,并添加了一些新变量。我想要做的是将这些新列附加到第一个表的右侧,通过标识变量连接。这很快变得复杂,所以这里有一个MRE:
df_1 <- data.frame(
id = id[c(1:3,5)],
first = first[c(1:3,5)],
last = last[c(1:3,5)],
a = a[c(1:3,5)],
b = b[c(1:3,5)]
)
df_2 <- data.frame(
id = id[c(1:3,5)],
first = first[c(1:3,5)],
last = last[c(1:3,5)],
c = c[c(1:3,5)],
d = d[c(1:3,5)]
)
df_3 <- data.frame(
id = id[c(1,2,4,6)],
first = first[c(1,2,4,6)],
last = last[c(1,2,4,6)],
e = e[c(1,2,4,6)],
f = f[c(1,2,4,6)]
)
df_goal <- data.frame(id, first, last, a, b, c, d, e, f)
模拟三个不同的文件:
df_goal
> df_goal
id first last a b c d e f
1 1 jeff teague 1 1 11 11 21 21
2 2 jimmy butler 2 2 12 12 22 22
3 3 andrew wiggins 3 3 13 13 NA NA
4 4 taj gibson 4 4 NA NA 24 24
5 5 karl-anthony towns NA NA 14 14 NA NA
6 6 jamal crawford NA NA NA NA 26 26
是我想要的,这就是它的样子:
full_join
请注意,这些是非常大的文件,并且列并不总是正确的顺序,因此我不能仅仅通过保留前三列来表示加入。
如果我对所有人进行df_all <- df_1 %>%
full_join(df_2, by = "id") %>%
full_join(df_3, by = "id")
> df_all
id first.x last.x a b first.y last.y c d first last e f
1 1 jeff teague 1 1 jeff teague 11 11 jeff teague 21 21
2 2 jimmy butler 2 2 jimmy butler 12 12 jimmy butler 22 22
3 3 andrew wiggins 3 3 andrew wiggins 13 13 <NA> <NA> NA NA
4 5 karl-anthony towns NA NA karl-anthony towns 14 14 <NA> <NA> NA NA
5 4 <NA> <NA> NA NA <NA> <NA> NA NA taj gibson 24 24
6 6 <NA> <NA> NA NA <NA> <NA> NA NA jamal crawford 26 26
,我每次都会重复这些名字:
for
我接下来要做的事情。我写了一个id
循环,我得到了每个数据框,只选择了(a)df_all
列,以及(b)名称尚未出现在full_join
数据框中的列,(c)做了dfs <- c("df_2", "df_3")
df_all1 <- df_1
for (i in dfs) {
df_all1 <- get(i)[!names(get(i)) %in% names(df_all1)[-1]] %>%
full_join(df_all1, .)
}
> df_all1
id first last a b c d e f
1 1 jeff teague 1 1 11 11 21 21
2 2 jimmy butler 2 2 12 12 22 22
3 3 andrew wiggins 3 3 13 13 NA NA
4 5 karl-anthony towns NA NA 14 14 NA NA
5 4 <NA> <NA> NA NA NA NA 24 24
6 6 <NA> <NA> NA NA NA NA 26 26
:
id
请注意,这意味着在第一个文件中出现 not 的情况缺少名称(这些代表我的数据中的关键人口统计变量)。如果bind_row
已经存在,我还尝试逐行进行并进行列连接,如果不存在则执行df_all2 <- df_1
for (i in dfs) {
for (k in 1:nrow(get(i))) {
if (get(i)[k, "id"] %in% df_all2$id) {
df_all2 <- get(i)[k, !names(get(i)) %in% names(df_all2)[-1]] %>%
left_join(df_all2, ., by = "id")
} else {
df_all2 <- bind_rows(
df_all2,
get(i)[k, !names(get(i)) %in% names(df_all2)[-1]]
)
}
}
}
。此代码引发了错误:
join
是一种仅使用选择列执行tidyr::spread
的方法,但必要时填写缺少的信息。我再次使用大量具有大量列的文件,所以我不能假设我知道任何列的位置;它必须由列名完成。
我还考虑过只包含一个新变量,即文件的日期,将它们全部堆叠在一起(“长”格式),然后使用tidyr::gather
和tidyverse
,但我还没有找到解决方案。
我并不认同base
(data.table
或df_all1 <- df_1
for (i in dfs) {
df_all1 <- get(i) %>%
full_join(
df_all1, .,
by = names(get(i))[names(get(i)) %in% names(df_all1)]
)
}
df_all1
会很棒,甚至某种方式在R中进行SQL连接)甚至是R;我也对使用pandas的Python解决方案持开放态度。
简短版本:如何通过标识号将新列连接到现有数据集 - 并填写非新列中的信息,但由于案例是新的,需要填写在?
可能的解决方案,根据Psidom:
{{1}}
这可能是一种更有效的方法吗?
答案 0 :(得分:1)
一旦melt
df_all,请使用full_join
。
library(data.table)
df <- melt(setDT(df_all),
measure.vars = patterns("^first", "^last"))
df <- unique(df[,-c("id", "variable")])
df[!is.na(df$value1),]
a b c d e f value1 value2
1: 1 1 11 11 21 21 jeff teague
2: 2 2 12 12 22 22 jimmy butler
3: 3 3 13 13 NA NA andrew wiggins
4: NA NA 14 14 NA NA karl-anthony towns
5: NA NA NA NA 24 24 taj gibson
6: NA NA NA NA 26 26 jamal crawford
答案 1 :(得分:1)
使用dplyr
的最简单的解决方案是在by
的调用中省略full_join()
参数。
library(dplyr)
df_1 %>%
full_join(df_2) %>%
full_join(df_3)
加入,按= c(&#34; id&#34;,&#34;首先&#34;,&#34;最后&#34;)
加入,by = c(&#34; id&#34;,&#34; first&#34;, &#34;最后&#34)id first last a b c d e f 1 1 jeff teague 1 1 11 11 21 21 2 2 jimmy butler 2 2 12 12 22 22 3 3 andrew wiggins 3 3 13 13 NA NA 4 5 karl-anthony towns NA NA 14 14 NA NA 5 4 taj gibson NA NA NA NA 24 24 6 6 jamal crawford NA NA NA NA 26 26
警告讯息:
1:列id
加入具有不同级别的因子,强制转换为字符向量
2:列first
加入不同级别的因子,强制转换为字符向量
3:列last
加入具有不同级别的因子,强制转换为字符向量
by
中?full_join
参数的文档说:如果NULL
,则默认*_join()
将使用所有常见变量进行自然连接两个表中的名称。
所以这相当于浏览by = c("id", "first", "last")
as proposed by Psidom。
如果要加入许多数据框,下面的代码可能会节省大量的输入:
Reduce(full_join, list(df_1, df_2, df_3))
结果(包括消息)与上述相同。