【问题标题】:fill in missing values by same values within the group(match known IMEI with missing cellphone model)用组内相同的值填充缺失值(匹配已知 IMEI 与缺失的手机型号)
【发布时间】:2016-09-22 23:54:29
【问题描述】:

我有一个时间序列/面板数据,包括加密的 IMEI(每个手机唯一,但每个用户不唯一)和手机品牌。 IMEI中的缺失值并不多,但手机品牌中的缺失值很多。由于唯一的 IMEI 对应于唯一的手机,我们可以通过 IMEI 推断缺失的品牌。 我的解决方案是使用我当前的数据构建一个品牌表和merge(by=IMEI) 的 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

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    这是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))
    

    【讨论】:

      【解决方案2】:

      这是一个经典的 R 方法:

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

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

      因为它需要一个数字参数,所以您不能只将因子转储到 ave 并获取最长的结果。你必须输入一个数字。好吧,因子映射到对应于水平的数字。因此,您可以找到平均水平(去除缺失后),然后将其用作原始水平的索引。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-08-26
        • 2012-10-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-26
        相关资源
        最近更新 更多