【发布时间】:2012-04-18 10:08:02
【问题描述】:
我正在寻找一种通用解决方案,用于使用第二个类似数据帧的内容更新一个大数据帧。我有几十个数据集,每个都有数千行和超过 10,000 列。 “更新”数据集将与其相应的“基础”数据集重叠,按行排列从百分之几到大约 50%。数据集有一个“键”列,在任何给定的数据集中,每个唯一键值只有一行。
基本规则是:如果给定单元格的更新数据集中存在非 NA 值,则将基础数据集中的相同单元格替换为该值。 (“相同单元格”表示“键”列和列名的值相同。)
请注意,更新数据集可能包含我可以使用 rbind 处理的新行(“插入”)。
因此,给定基本数据框“df1”,其中“K”列是唯一键列,“P1”..“P3”代表 10,000 列,其名称会因一对数据集而异:
K P1 P2 P3
1 A 1 1 1
2 B 1 1 1
3 C 1 1 1
...和更新数据框“df2”:
K P1 P2 P3
1 B 2 NA 2
2 C NA 2 2
3 D 2 2 2
我需要的结果如下,其中“B”和“C”的 1 被 2 覆盖,但未被 NA 覆盖:
K P1 P2 P3
1 A 1 1 1
2 B 2 1 2
3 C 1 2 2
4 D 2 2 2
这似乎不是一个合并候选者,因为合并给了我重复的行(相对于“键”列)或重复的列(例如 P1.x、P1.y),我必须对其进行迭代以某种方式崩溃。
我尝试使用最终行/列的维度预先分配一个矩阵,并用 df1 的内容填充它,然后迭代 df2 的重叠行,但我无法获得优于每秒 20 个单元格的性能,需要数小时才能完成(与 SAS 中等效的 DATA 步 UPDATE 功能相比需要数分钟)。
我确定我遗漏了一些东西,但找不到可比较的例子。
我看到 ddply 用法看起来很接近,但不是通用解决方案。 data.table 包似乎没有帮助,因为对我来说这是一个连接问题并不明显,至少通常不会超过这么多列。
此外,仅关注相交行的解决方案就足够了,因为我可以识别其他行并将它们绑定到其中。
这里是一些代码来制作上面的数据框:
cat("K,P1,P2,P3", "A,1,1,1", "B,1,1,1", "C,1,1,1", file="f1.dat", sep="\n");
cat("K,P1,P2,P3", "B,2,,2", "C,,2,2", "D,2,2,2", file="f2.dat", sep="\n");
df1 <- read.table("f1.dat", sep=",", header=TRUE, stringsAsFactors=FALSE);
df2 <- read.table("f2.dat", sep=",", header=TRUE, stringsAsFactors=FALSE);
谢谢
【问题讨论】:
-
我收回这不是重复的。我读得不够仔细。您希望将一个 df 的 NA 替换为另一个 df 进行合并。有点复杂。
-
在
data.table中,一种方法是将df1和df2展平为3 列:(K,P,val),每列都有一个2 列键(K,P)。然后df1[df2,val:=df2.val]然后展开。或者,保持相同的结构,通过df2循环执行df1[k,p:=value,with=FALSE],这将很快,因为data.tables 上的循环要快得多。如果您喜欢循环方法,那么set()甚至比:=更快。 -
@MatthewDowle 带有
df1[df2,val:=df2.val]的标准化(扁平化)路由给出Error in := (val, df2.val) : := is defined for use in j only; i.e., DT[i,col:=1L] not DT[i,col]:=1L or DT[i]$col:=1L.。 -
df1必须是data.table;例如df1=as.data.table(df1)。我将在该错误消息中添加一些内容以建议检查该类型。
标签: r dataframe data.table