根据组中的可用值填充缺失值
Fill missing values based on available values in a group
我想填补缺失值不是基于 LOCF,而是基于该组可用的值。虽然我能够根据 的回答做到这一点,但我正在寻找关于 :
的解释
问题a)(Final_Rank = Final_Rank[1])
。楼主没有解释这部分。
问题b)还有其他更高效(速度方面)的方法吗?我看到一个使用 Data.Table
,但我不太熟悉它。我无法使用 Data.Table
执行此操作。实际数据大小为 2GB。
这是我的数据:
dput(DF)
structure(list(SL3 = c("SE", "SE", "SE", "SE", "SE", "SE", "SW",
"SW", "SW", "SW", "SW", "SW"), SL6 = c("SL123", "SL123", "SL123",
"SL123", "SL123", "SL124", "SL123", "SL123", "SL123", "SL123",
"SL123", "SL124"), Sname = c("123 Inc", "123 Inc", "123 Inc",
"123 Inc", "123 Inc", "234 Inc", "345 Inc", "345 Inc", "345 Inc",
"345 Inc", "345 Inc", "567 Inc"), Group = c("Red", "Sapphire",
"Red", "Sapphire", "White", "Red", "Red", "Sapphire", "Red",
"Sapphire", "White", "Red"), Final_Rank = c("High", "Medium",
NA, NA, "Low", NA, "High", "Medium", NA, NA, "Low", NA), Value = c(1,
2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6)), .Names = c("SL3", "SL6", "Sname",
"Group", "Final_Rank", "Value"), row.names = c(NA, 12L), class = "data.frame")
这是我的代码:
DF%>%
dplyr::group_by(SL3,SL6, Sname, Group) %>%
dplyr::arrange(SL3,SL6, Sname, Group, Final_Rank) %>%
dplyr::mutate(Final_Rank = Final_Rank[1])
预期输出:
SL3 SL6 Sname Group Final_Rank Value
<chr> <chr> <chr> <chr> <chr> <dbl>
1 SE SL123 123 Inc Red High 1
2 SE SL123 123 Inc Red High 3
3 SE SL123 123 Inc Sapphire Medium 2
4 SE SL123 123 Inc Sapphire Medium 4
5 SE SL123 123 Inc White Low 5
6 SE SL124 234 Inc Red <NA> 6
7 SW SL123 345 Inc Red High 1
8 SW SL123 345 Inc Red High 3
9 SW SL123 345 Inc Sapphire Medium 2
10 SW SL123 345 Inc Sapphire Medium 4
11 SW SL123 345 Inc White Low 5
12 SW SL124 567 Inc Red <NA> 6
正如我们在上面看到的,因为第 12 行和第 6 行在别处不存在 Final_Rank,所以我会得到 NA
。如果我使用 tidyr::fill()
,那些就会被填满。
如果有人能帮我解决以上两个问题,我将不胜感激。
对于 A 部分,这是@Haboryme 的评论(保留在答案中):
Final_Rank = Final_Rank[1]
simply replaces Final_Rank
with the first value of Final_Rank
. If there is a non-NA it will be the first. – Haboryme
稍微扩展一下,当使用 group_by
时,它将 select 组 中 Final_Rank
的第一个条目。这只是第一个,因为您在代码中被 Final_Rank
arrange
'ing。您可以将 Final_Rank[1]
替换为任何选定的值,包括常量(例如 "Missing"
)或计算值(例如 paste(Final_Rank %>% unique %>% sort, sep ="; ")
以连接该组中的所有值)。
看看时间,mutate
描述的方法已经很不错了。 data.table
解决方案往往会快一点,但我发现语法非常困难,以至于我在 run-time 削减的时间在 coding/debugging(然后是一些)中丢失了,除非我是 运行代码一个lot.
这是当前 mutate
解决方案的快速基准测试(使用 microbenchmark
包),建议的 fill
解决方案,以及生成 "look up table" 的解决方案所需的条目,然后将其重新加入。请注意,如果有不止一个有效的 Final_Rank
条目,fill
将给出与其他条目不同的答案。
library(microbenchmark)
microbenchmark(
mutate =
DF%>%
group_by(SL3,SL6, Sname, Group) %>%
arrange(SL3,SL6, Sname, Group, Final_Rank) %>%
mutate(Final_Rank = ifelse(is.na(Final_Rank), Final_Rank[1], Final_Rank))
, fill =
DF%>%
group_by(SL3,SL6, Sname, Group) %>%
arrange(SL3,SL6, Sname, Group, Final_Rank) %>%
fill(Final_Rank)
, left_join =
DF%>%
select(-Value) %>%
group_by(SL3,SL6, Sname, Group) %>%
arrange(Final_Rank) %>%
slice(1) %>%
rename(newRank = Final_Rank) %>%
left_join(DF, .) %>%
arrange(SL3,SL6, Sname, Group)
)
给予
Unit: milliseconds
expr min lq mean median uq max neval
mutate 1.783668 1.848683 1.954992 1.904577 1.968923 3.093098 100
fill 3.299220 3.399997 3.558219 3.491215 3.573784 4.756986 100
left_join 3.097166 3.214982 3.379452 3.300272 3.420206 4.653970 100
请注意,mutate 解决方案比其他两个解决方案快一点,尽管可能存在其他解决方案(如果组规模增长,这些解决方案的规模可能会有所不同)。
最后,请注意当前的实现将 Final_Rank
中的 ALL 条目替换为组中的第一个条目。如果您只想替换 缺失的 条目,则需要使用 ifelse
(或 fill
,如上所述),如下所示:
DF%>%
group_by(SL3,SL6, Sname, Group) %>%
arrange(SL3,SL6, Sname, Group, Final_Rank) %>%
mutate(Final_Rank = ifelse(is.na(Final_Rank), Final_Rank[1], Final_Rank))
我将其添加到 microbenchmark
并且它似乎并没有显着降低速度:
Unit: milliseconds
expr min lq mean median uq max neval
mutate 1.752267 1.835038 1.937181 1.900086 1.946848 3.197292 100
fill 3.289838 3.414916 3.626607 3.507186 3.618336 5.857506 100
left_join 3.052692 3.209808 3.371702 3.260593 3.377899 6.924646 100
ifelse 1.771460 1.813426 1.935845 1.883497 1.951977 3.113328 100
我想填补缺失值不是基于 LOCF,而是基于该组可用的值。虽然我能够根据
问题a)(Final_Rank = Final_Rank[1])
。楼主没有解释这部分。
问题b)还有其他更高效(速度方面)的方法吗?我看到一个使用 Data.Table
,但我不太熟悉它。我无法使用 Data.Table
执行此操作。实际数据大小为 2GB。
这是我的数据:
dput(DF)
structure(list(SL3 = c("SE", "SE", "SE", "SE", "SE", "SE", "SW",
"SW", "SW", "SW", "SW", "SW"), SL6 = c("SL123", "SL123", "SL123",
"SL123", "SL123", "SL124", "SL123", "SL123", "SL123", "SL123",
"SL123", "SL124"), Sname = c("123 Inc", "123 Inc", "123 Inc",
"123 Inc", "123 Inc", "234 Inc", "345 Inc", "345 Inc", "345 Inc",
"345 Inc", "345 Inc", "567 Inc"), Group = c("Red", "Sapphire",
"Red", "Sapphire", "White", "Red", "Red", "Sapphire", "Red",
"Sapphire", "White", "Red"), Final_Rank = c("High", "Medium",
NA, NA, "Low", NA, "High", "Medium", NA, NA, "Low", NA), Value = c(1,
2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6)), .Names = c("SL3", "SL6", "Sname",
"Group", "Final_Rank", "Value"), row.names = c(NA, 12L), class = "data.frame")
这是我的代码:
DF%>%
dplyr::group_by(SL3,SL6, Sname, Group) %>%
dplyr::arrange(SL3,SL6, Sname, Group, Final_Rank) %>%
dplyr::mutate(Final_Rank = Final_Rank[1])
预期输出:
SL3 SL6 Sname Group Final_Rank Value
<chr> <chr> <chr> <chr> <chr> <dbl>
1 SE SL123 123 Inc Red High 1
2 SE SL123 123 Inc Red High 3
3 SE SL123 123 Inc Sapphire Medium 2
4 SE SL123 123 Inc Sapphire Medium 4
5 SE SL123 123 Inc White Low 5
6 SE SL124 234 Inc Red <NA> 6
7 SW SL123 345 Inc Red High 1
8 SW SL123 345 Inc Red High 3
9 SW SL123 345 Inc Sapphire Medium 2
10 SW SL123 345 Inc Sapphire Medium 4
11 SW SL123 345 Inc White Low 5
12 SW SL124 567 Inc Red <NA> 6
正如我们在上面看到的,因为第 12 行和第 6 行在别处不存在 Final_Rank,所以我会得到 NA
。如果我使用 tidyr::fill()
,那些就会被填满。
如果有人能帮我解决以上两个问题,我将不胜感激。
对于 A 部分,这是@Haboryme 的评论(保留在答案中):
Final_Rank = Final_Rank[1]
simply replacesFinal_Rank
with the first value ofFinal_Rank
. If there is a non-NA it will be the first. – Haboryme
稍微扩展一下,当使用 group_by
时,它将 select 组 中 Final_Rank
的第一个条目。这只是第一个,因为您在代码中被 Final_Rank
arrange
'ing。您可以将 Final_Rank[1]
替换为任何选定的值,包括常量(例如 "Missing"
)或计算值(例如 paste(Final_Rank %>% unique %>% sort, sep ="; ")
以连接该组中的所有值)。
看看时间,mutate
描述的方法已经很不错了。 data.table
解决方案往往会快一点,但我发现语法非常困难,以至于我在 run-time 削减的时间在 coding/debugging(然后是一些)中丢失了,除非我是 运行代码一个lot.
这是当前 mutate
解决方案的快速基准测试(使用 microbenchmark
包),建议的 fill
解决方案,以及生成 "look up table" 的解决方案所需的条目,然后将其重新加入。请注意,如果有不止一个有效的 Final_Rank
条目,fill
将给出与其他条目不同的答案。
library(microbenchmark)
microbenchmark(
mutate =
DF%>%
group_by(SL3,SL6, Sname, Group) %>%
arrange(SL3,SL6, Sname, Group, Final_Rank) %>%
mutate(Final_Rank = ifelse(is.na(Final_Rank), Final_Rank[1], Final_Rank))
, fill =
DF%>%
group_by(SL3,SL6, Sname, Group) %>%
arrange(SL3,SL6, Sname, Group, Final_Rank) %>%
fill(Final_Rank)
, left_join =
DF%>%
select(-Value) %>%
group_by(SL3,SL6, Sname, Group) %>%
arrange(Final_Rank) %>%
slice(1) %>%
rename(newRank = Final_Rank) %>%
left_join(DF, .) %>%
arrange(SL3,SL6, Sname, Group)
)
给予
Unit: milliseconds
expr min lq mean median uq max neval
mutate 1.783668 1.848683 1.954992 1.904577 1.968923 3.093098 100
fill 3.299220 3.399997 3.558219 3.491215 3.573784 4.756986 100
left_join 3.097166 3.214982 3.379452 3.300272 3.420206 4.653970 100
请注意,mutate 解决方案比其他两个解决方案快一点,尽管可能存在其他解决方案(如果组规模增长,这些解决方案的规模可能会有所不同)。
最后,请注意当前的实现将 Final_Rank
中的 ALL 条目替换为组中的第一个条目。如果您只想替换 缺失的 条目,则需要使用 ifelse
(或 fill
,如上所述),如下所示:
DF%>%
group_by(SL3,SL6, Sname, Group) %>%
arrange(SL3,SL6, Sname, Group, Final_Rank) %>%
mutate(Final_Rank = ifelse(is.na(Final_Rank), Final_Rank[1], Final_Rank))
我将其添加到 microbenchmark
并且它似乎并没有显着降低速度:
Unit: milliseconds
expr min lq mean median uq max neval
mutate 1.752267 1.835038 1.937181 1.900086 1.946848 3.197292 100
fill 3.289838 3.414916 3.626607 3.507186 3.618336 5.857506 100
left_join 3.052692 3.209808 3.371702 3.260593 3.377899 6.924646 100
ifelse 1.771460 1.813426 1.935845 1.883497 1.951977 3.113328 100