这是我的CSV数据样本。它包含~10列。
Product_id Product_Weight Product_Name Shop_Name ...
[1] A 10 xxxx Walmart
[2] B 12 yyyy Target
[3] C 11 zzzz Target
[4] A NA xxxx Walmart
[5] C NA zzzz Target
我想分别用10和11填充第4行和第5行中的NA(因为A和C的产品重量已经从第1行和第3行得知)。我希望最终的数据框像这样
Product_id Product_Weight Product_Name Shop_Name ...
[1] A 10 xxxx Walmart
[2] B 12 yyyy Target
[3] C 11 zzzz Target
[4] A 10 xxxx Walmart
[5] C 11 zzzz Target
在R中执行此操作的最佳方法是什么?
答案 0 :(得分:9)
虽然问题是“先前发生”,但这样做会有一个缺点,即如果Product_Weight
中的第一个Product_id
为NA
,那么即使我们无法填写我知道后续Product_Weight
中的Product_id
,所以我们采用相同Product_id
的所有非NA的平均值而不是前一次出现。因为这些都应该是相同的,它们的平均值是它们的共同价值。
如果您确实想要上一次出现,请使用Prev
函数,其中:
Prev <- function(x) na.locf(x, na.rm = FALSE)
代替(1)和(3)中的na.aggregate
而不使用(2)。
以下解决方案具有以下优点:
保留输入的顺序
即使任何Product_Weight
中的第一个Product_id
为NA
不要修改输入
第一个解决方案的另一个优势是只有一行代码(加上library
语句),第二个解决方案还有一个不使用任何软件包的优势。
1)zoo :: na.aggregate 我们在动物园包中使用na.aggregate
(用非NA的平均值替换所有NAs)并将其应用于{{ 1}}分别为每个Product_Weight
。
Product_id
,并提供:
library(zoo)
transform(DF, Product_Weight = ave(Product_Weight, Product_id, FUN = na.aggregate))
2)没有软件包或者使用 Product_id Product_Weight Product_Name Shop_Name
1 A 10 xxxx Walmart
2 B 12 yyyy Target
3 C 11 zzzz Target
4 A 10 xxxx Walmart
5 C 11 zzzz Target
代替Mean
,其中na.aggregate
定义为:
Mean
3)dplyr / zoo 按Mean <- function(x) replace(x, is.na(x), mean(x, na.rm = TRUE))
添加行号,分组,使用Product_id
填写新的解决方案,如下所示,或{{ 1}},安排回原始订单并删除行号:
na.aggregate
注意:这用于输入Mean
:
library(dplyr)
library(zoo)
DF %>%
mutate(row = row_number()) %>%
group_by(Product_id) %>%
mutate(Product_Weight = na.aggregate(Product_Weight)) %>%
ungroup() %>%
arrange(row) %>%
select(-row)
答案 1 :(得分:6)
dplyr
和tidyr
的另一个选项:
library(dplyr); library(tidyr);
df %>% group_by(Product_id) %>% fill(Product_Weight)
Source: local data frame [5 x 4]
Groups: Product_id [3]
Product_id Product_Weight Product_Name Shop_Name
(fctr) (int) (fctr) (fctr)
1 A 10 xxxx Walmart
2 A 10 xxxx Walmart
3 B 12 yyyy Target
4 C 11 zzzz Target
5 C 11 zzzz Target
结果按Product_id排序。
答案 2 :(得分:2)
以下是基本R命令的解决方案:
# create lookup table with item and weight combinations
lookup<-unique(df[complete.cases(df[ ,1:2]),])
# find the NAs needing replacement: which(is.na(df$weight))
# find index in lookup tabe:match(df$a[which(is.na(df$weight))
# subset: df$weight[which(is.na(df$weight))
df$weight[which(is.na(df$weight))]<-lookup$weight[match(df$Product_id[which(is.na(df$weight))], lookup$Product_id)]
很可能不如上面提到的dplyr / tidyr解决方案有效。