通过组内相同的值填充缺失值(匹配已知的IMEI与丢失的手机型号)

时间:2016-09-22 23:54:30

标签: r dplyr

我有时间序列/面板数据,包括加密的IMEI(每个手机独一无二,但不是每个用户独一无二)和手机品牌。 IMEI中不存在太多缺失值,但手机品牌中存在大量缺失值。由于独特的IMEI对应一个独特的手机,我们可以通过IMEI推断出缺失的品牌。 我的解决方案是使用我当前的数据构建IMEI到品牌表和merge(by=IMEI)。 我只是好奇。还有其他办法吗?例如,在dplyr或data.table中,或者只是r-base函数。我的数据很大,有大约300万个观测值。

注意:用户可以拥有多个设备/ IMEI;品牌在开始时间,中间或结束时缺少一些时间。

# create sample data
user<-rep(letters[1:5],each=6)
time<-rep(1:6,5)
imei<-c(rep(100,6),rep(200,4),NA,201,rep(300,6),rep(400,3),401,404,404,rep(500,5),NA)
brand<-c(rep('Apple',3),NA,NA,'Apple',NA,rep('ZTE',4),NA,NA,NA,NA,rep('Samsung',3),NA,'Huawei',NA,'Nokia','HTC',NA,rep('Moto',6))
dt<-data.frame(time,user,imei,brand)

    #data
  time user imei   brand
1     1    a  100   Apple
2     2    a  100   Apple
3     3    a  100   Apple
4     4    a  100    <NA>
5     5    a  100    <NA>
6     6    a  100   Apple
7     1    b  200    <NA>
8     2    b  200     ZTE
9     3    b  200     ZTE
10    4    b  200     ZTE
11    5    b   NA     ZTE
12    6    b  201    <NA>
13    1    c  300    <NA>
14    2    c  300    <NA>
15    3    c  300    <NA>
16    4    c  300 Samsung
17    5    c  300 Samsung
18    6    c  300 Samsung
19    1    d  400    <NA>
20    2    d  400  Huawei
21    3    d  400    <NA>
22    4    d  401   Nokia
23    5    d  404     HTC
24    6    d  404    <NA>
25    1    e  500    Moto
26    2    e  500    Moto
27    3    e  500    Moto
28    4    e  500    Moto
29    5    e  500    Moto
30    6    e   NA    Moto

2 个答案:

答案 0 :(得分:2)

这是data.table方法:

library(data.table)
setDT(dt)
setkey(dt, imei)
dt[dt, brand := unique(na.omit(brand)), imei]
#     time user imei   brand
#  1:    5    b   NA     ZTE
#  2:    6    e   NA    Moto
#  3:    1    a  100   Apple
#  4:    2    a  100   Apple
#  5:    3    a  100   Apple
#  6:    4    a  100   Apple
#  7:    5    a  100   Apple
#  8:    6    a  100   Apple
#  9:    1    b  200     ZTE
# 10:    2    b  200     ZTE
# 11:    3    b  200     ZTE
# 12:    4    b  200     ZTE
# 13:    6    b  201      NA
# 14:    1    c  300 Samsung
# 15:    2    c  300 Samsung
# 16:    3    c  300 Samsung
# 17:    4    c  300 Samsung
# 18:    5    c  300 Samsung
# 19:    6    c  300 Samsung
# 20:    1    d  400  Huawei
# 21:    2    d  400  Huawei
# 22:    3    d  400  Huawei
# 23:    4    d  401   Nokia
# 24:    5    d  404     HTC
# 25:    6    d  404     HTC
# 26:    1    e  500    Moto
# 27:    2    e  500    Moto
# 28:    3    e  500    Moto
# 29:    4    e  500    Moto
# 30:    5    e  500    Moto
#     time user imei   brand

这是dplyr + zoo::na.locf方法:

library(dplyr)
library(zoo)
fillna <- function(x) na.locf(na.locf(x, na.rm = FALSE), fromLast = TRUE, na.rm = FALSE)
dt <- dt %>% group_by(imei) %>% mutate(brand = fillna(brand))

答案 1 :(得分:1)

这是一种经典的R方式:

dt$brand <- levels(dt$brand)[ave(as.numeric(dt$brand), dt$imei, FUN= function(x) mean(x, na.rm=TRUE))]

ave取一个数字参数,并按其他参数的级别对其执行FUN。然后它返回一个与原始数据长度相同的向量,每个imei具有相同的级别。

因为它需要一个数字参数,所以你不能将因子转储到ave中并获得最长的结果。你必须投入一个数字。那么,因子映射到与水平相对应的数字。因此,您可以找到平均水平(删除失踪后),然后将其用作原始水平的索引。