【问题标题】:Subset-join-replace using R data.table使用 R data.table 进行子集连接替换
【发布时间】:2021-03-11 05:19:21
【问题描述】:

我有一个由 id-name 对组成的数据集。这些对可以出现多次。在某些行中缺少 name 列中的值,在其他行中缺少 id

id_name = data.table(stringsAsFactors=FALSE,
                 id = c("x123", "xy234","x123",NA,"z123","y123","d654","d654"),
                 name = c("john", "mary", NA,"mary","bob","bob", "john",NA)
                     )

我想将一列中的 NA 值替换为另一行中的(非缺失)值,并使用另一列作为查找值。结果应该是:

            id name
      1:  x123 john
      2: xy234 mary
      3:  x123 john
      4: xy234 mary
      5:  z123  bob
      6:  y123  bob
      7:  d654 john
      8:  d654 john

实现这一点的惯用方式是什么,data.table 方式?以下仅更新名称列的方法不会产生错误,但也不会更新数据集:

id_name[is.na(name)][id_name[!is.na(name)], on="id", name:=i.name]
> id_name
      id name
1:  x123 john
2: xy234 mary
3:  x123 <NA>
4:  <NA> mary
5:  z123  bob
6:  y123  bob
7:  d654 john
8:  d654 <NA>

但是,没有更新的只是子集并加入:

id_name[is.na(name)][id_name[!is.na(name)], on="id",nomatch=0L]

     id name i.name
1: x123 <NA>   john
2: d654 <NA>   john

更新

更新了 MRE 以明确某些名称可以与 2 个 ID 相关联。两个 id 都必须保留。

【问题讨论】:

    标签: r join replace data.table subset


    【解决方案1】:

    我想你正在寻找:

    id_name[is.na(name), name :=
        id_name[!is.na(name)][.SD, on=.(id), x.name]
    ]
    id_name[is.na(id), id := 
        id_name[!is.na(id)][.SD, on=.(name), mult="first", x.id]
    ]
    id_name
    

    【讨论】:

    • 我喜欢您的解决方案,因为它是一种纯 data.table 方法
    【解决方案2】:

    我们可以按'name'、'id'分组,并将'id'中的NA元素替换为第一个非NA值

    id_name[, id := id[!is.na(id)][1], name]
    id_name[, name := name[!is.na(name)], id]
    

    -输出

    id_name
    #     id  name
    #1:  x123  john
    #2: xy234 marry
    #3:  x123  john
    #4: xy234 marry
    

    更新

    我们可以从tidyr使用fill

    library(tidyr)
    id_name1 <- id_name[, fill(.SD, id), name][,  fill(.SD, name) , id]
    id_name1
    #      id name
    #1:  x123 john
    #2:  x123 john
    #3:  d654 john
    #4:  d654 john
    #5: xy234 mary
    #6: xy234 mary
    #7:  z123  bob
    #8:  y123  bob
    

    【讨论】:

    • 虽然这种方法确实会更新缺失值,但它也会删除可能存在于相同 id/name 的任何其他记录。我正在寻找的方法应该只更新缺失值的记录而不丢弃其他记录。
    • @MariusPetruc 你能用更通用的例子更新你的例子吗
    【解决方案3】:

    您可以使用zoona.locf 来填充缺失值。

    library(zoo)
    library(data.table)
    
    id_name[, id := na.locf(id), name]
    id_name[, name := na.locf(name), id]
    id_name
    
    #      id  name
    #1:  x123  john
    #2: xy234 marry
    #3:  x123  john
    #4: xy234 marry
    

    【讨论】:

    • data.table 已经有 fillna 功能,所以不需要额外的包
    • @jangorecki 好的...我不知道,谢谢。但是,它似乎只适用于数值而不适用于字符值?
    猜你喜欢
    • 2014-03-02
    • 1970-01-01
    • 2014-05-14
    • 1970-01-01
    • 2014-03-28
    • 2013-01-08
    • 2017-12-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多