【问题标题】:tidyverse spread with duplicate keys and fill NAs based on unique keystidyverse 使用重复键传播并根据唯一键填充 NA
【发布时间】: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
)

idproperty 分组并添加一个键接近但留下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”时,按 idproperty 分组时生成的密钥对于“A”的两个值将具有 12,但仅1 代表“B”。这会在传播时为 B 创建一个缺失值,因为“B”没有 key==2

标签: r dplyr tidyr tidyverse


【解决方案1】:

您可以从tidyr 使用fill

library(dplyr)
library(tidyr)

ex %>% 
  group_by(id, property) %>%
  mutate(key = row_number()) %>%
  spread(property, value) %>% 
  select(-key) %>%
  group_by(id) %>%
  fill(-id)

结果:

# A tibble: 3 x 3
# Groups:   id [2]
     id     A     B
  <dbl> <dbl> <dbl>
1     1     9     7
2     1     8     7
3     2     6     5

【讨论】:

  • fill 很好,但看起来它不是基于 id 而是仅基于下一行或上一行。这似乎很脆弱——即使先按 id 排序,我们也不能确定它总是具有相同 id 的行。
  • @cboettig 你可以随时group_by(id)。查看我的编辑。
  • 我猜在这种情况下它实际上已经被id分组了,很高兴知道填充尊重组
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-04
  • 1970-01-01
  • 1970-01-01
  • 2022-08-18
  • 1970-01-01
  • 2017-09-01
  • 2019-12-26
相关资源
最近更新 更多