如何从具有数据的其他行推断 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.locf0
将 NA
元素替换为以前的 non-NA 值,如果有 NA 作为开始元素,则在第一个 na.locf0
之上应用带有 fromLast = TRUE
的 na.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
在我的示例中,我有一个 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.locf0
将 NA
元素替换为以前的 non-NA 值,如果有 NA 作为开始元素,则在第一个 na.locf0
之上应用带有 fromLast = TRUE
的 na.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