【发布时间】:2018-05-01 08:58:00
【问题描述】:
考虑最小的例子:
library(tidyverse)
ex <-tribble(
~id, ~property, ~value,
1, "A", 9,
1, "A", 8,
1, "B", 7,
2, "A", 6,
2, "B", 5
)
我的目标是将属性分散到列中以获取此表:
tribble(
~id, ~A, ~B,
1, 9, 7,
1, 8, 7,
2, 6, 5
)
按id 和property 分组并添加一个键接近但留下NA:
## almost but not quite
ex %>%
group_by(id, property) %>%
mutate(key = row_number()) %>%
spread(property, value) %>%
select(-key) -> X
X
给:
id A B
1 1 9 7
2 1 8 NA
3 2 6 5
我可以在最小的例子中解决这个问题,方法是按每个 property 拆分上述内容,删除 NA,然后通过 id 重新加入:
inner_join(
na.omit(select(X, id, A)),
na.omit(select(X, id, B))
)
但显然这并不能推广到任意一组属性。有什么更好的tidyverse 策略来做到这一点?
注意:之前的几个问题谈到了前半部分,例如构造key 列,以便spread 不会失败,但看不到解决NAs 的内容。
【问题讨论】:
-
B 的值只有 2 个,A 的值只有 3 个,为什么你期望它不会给 B 的
NA?您只是想用以前的值填充 NA 吗? -
@user 因为我们知道 id 为 1 的对象的属性 B 基于 id 1 的其他行。本质上,属性 A 是可以多值的(想想 id 为 1 的纸可以有多个“关键字”(属性 A),每个出现在单独的行中,因为我不喜欢表中的列表值。
-
是的,但是为什么您希望 程序 知道呢?当 id1 中只有一个“B”但有两个“A”时,按
id和property分组时生成的密钥对于“A”的两个值将具有1和2,但仅1代表“B”。这会在传播时为 B 创建一个缺失值,因为“B”没有key==2。