如何从具有数据的其他行推断 R 数据框中的缺失值?

How to infer missing values in a R data frame from other rows that have the data?

在我的示例中,我有一个 table,其产品在商店 1 中具有唯一 ID,在商店 2 中具有不同(但也是唯一)的 ID。

通常,相同的产品在商店 1 中始终具有相同的 ID,在商店 2 中始终具有相同的 ID。也就是说,如果我只知道这些变量中的一个,我应该能够填写其余的。

但是,我没有一个简洁的参考 table 或列表来显示哪些产品和 ID 属于一起。我所要开始的是一个 table 有很多像这样的空白:

我想使用 table 中已有的信息来填补空白,如下所示:

是否有可以执行此操作的 R 函数,或者您将如何处理?

#Example data
df <- data.frame(
  c(NA, "Shovel", NA, NA, "Gloves", NA),
  c("W06", NA, "W06", "W11", "W11", NA),
  c("EF001", "EF001", NA, NA, "EF004", "EF004")
)
colnames(df) <- c("Product", "Store1_ID", "Store2_ID")


df2 <- data.frame(
  c("Shovel",NA, NA, NA, "Gloves", NA),
  c(NA, "W06", "W06", "W11", "W11", NA),
  c("EF001", "EF001", NA, NA, "EF004", "EF004")
)
colnames(df2) <- c("Product", "Store1_ID", "Store2_ID")

创建分组索引列,在循环 across 'Store' 列后,应用 na.locf0NA 元素替换为以前的 non-NA 值,如果有 NA 作为开始元素,则在第一个 na.locf0 之上应用带有 fromLast = TRUEna.locf0,将其转换为带有 duplicated 的逻辑列,取反(!) 以便它 returns 对第一个 non-duplicated 元素为 TRUE,对其他元素为 FALSE,得到累积和 (cumsum),使用 pmax 逐元素查找最大索引创建 'grp',然后我们在其他列

上使用 fill
library(tidyr)
library(dplyr)
library(purrr)
df %>% 
  group_by(grp = invoke(pmax, across(starts_with('Store'), 
    ~ cumsum(!duplicated(zoo::na.locf0(zoo::na.locf0(.x), 
           fromLast = TRUE))), .names = "{.col}_new")))  %>% 
 fill(everything(), .direction = "downup") %>%
 ungroup %>% 
 select(-grp)
# A tibble: 6 × 3
  Product Store1_ID Store2_ID
  <chr>   <chr>     <chr>    
1 Shovel  W06       EF001    
2 Shovel  W06       EF001    
3 Shovel  W06       EF001    
4 Gloves  W11       EF004    
5 Gloves  W11       EF004    
6 Gloves  W11       EF004   
  • .names 用于创建新列,但在本例中不需要

df2

相同的输出
df2 %>% 
  group_by(grp = invoke(pmax, across(starts_with('Store'), 
    ~ cumsum(!duplicated(zoo::na.locf0(zoo::na.locf0(.x), 
     fromLast = TRUE))), .names = "{.col}_new"))) %>% 
  fill(everything(), .direction = "downup") %>%
  ungroup %>% 
  select(-grp)

-输出

# A tibble: 6 × 3
  Product Store1_ID Store2_ID
  <chr>   <chr>     <chr>    
1 Shovel  W06       EF001    
2 Shovel  W06       EF001    
3 Shovel  W06       EF001    
4 Gloves  W11       EF004    
5 Gloves  W11       EF004    
6 Gloves  W11       EF004    

更新二:对于新数据集df2

添加 .direction 参数以填充分组变量的两个方向,然后应用 fill_run 函数:

library(dplyr)
library(runner)

df2 %>% 
  fill(Store1_ID, .direction = "updown") %>% 
  group_by(Store1_ID) %>% 
  mutate(across(everything(), ~fill_run(., run_for_first = TRUE)))
  Product Store1_ID Store2_ID
  <chr>   <chr>     <chr>    
1 Shovel  W06       EF001    
2 Shovel  W06       EF001    
3 Shovel  W06       EF001    
4 Gloves  W11       EF004    
5 Gloves  W11       EF004    
6 Gloves  W11       EF004 

更新考虑分组:

library(dplyr)
library(runner)

df %>% 
  fill(Store1_ID) %>% 
  group_by(Store1_ID) %>% 
  mutate(across(everything(), ~fill_run(., run_for_first = TRUE)))
   Product Store1_ID Store2_ID
  <chr>   <chr>     <chr>    
1 Shovel  W06       EF001    
2 Shovel  W06       EF001    
3 Shovel  W06       EF001    
4 Gloves  W11       EF004    
5 Gloves  W11       EF004    
6 Gloves  W11       EF004