【问题标题】:How to split/parse long strings into tabular data with R data.table/data.frame?如何使用 R data.table/data.frame 将长字符串拆分/解析为表格数据?
【发布时间】:2018-10-22 23:30:29
【问题描述】:

我有一个 R data.table,其中有一列格式奇怪的数据,我需要对其进行解析。对于每一行,都有一个列identity,格式如下:

identity
cat:211:93|dog:616:58|bird:1270:46|fish:2068:31|horse:614:1|cow:3719:1012

格式为name:total_number:count_number,以|分隔

data.table的一个例子如下:

library(data.table)

foo = data.table(name = c('Luna', 'Bob', 'Melissa'), 
    number = c(23, 37, 33), 
    identity = c('cat:311:93|dog:516:58|bird:2270:46|fish:1268:31|horse:514:1|cow:319:12', 'bird:1270:35|fish:2068:11|horse:614:44|cow:319:21', 'fish:72:41'))

print(foo)
name        number    identity
'Luna'      23        cat:311:93|dog:516:58|bird:2270:46|fish:1268:31|horse:514:1|cow:319:12
'Bob'       37        bird:1270:35|fish:2068:11|horse:614:44|cow:319:21
'Melissa'   33        fish:72:41

我的问题是如何解析这些行,使每个name 成为一个新列,并且数字被计算为一个分数,count_number/total_number

正确的格式如下:

name        number    cat        dog         bird        fish        horse       cow
'Luna'      23        0.2990354  0.1124031   0.02026432  0.02444795  0.001945525 0.03761755
'Bob'       37        NA         NA          0.02755906   0.005319149    0.001628664     0.03761755
'Melissa'   33        NA         NA          NA          0.5694444   NA       NA

如果我事先知道列的“名称”,我该如何解析这些行?

我认为应该有一些方法可以使用data.table::tstrsplit(),例如

tstrsplit(foo$identity, "|", fixed=TRUE)

(我也很乐意使用 data.frame 或 dplyr。)

【问题讨论】:

    标签: r parsing dataframe data.table


    【解决方案1】:

    在计算比率并重新调整为所需格式之前,您可能可以按 | 分割、融化,然后再按 : 分割。

    library(data.table)
    #step 4: reshape into desired wide format
    dcast(
        #step 1: split by | and get the elements into a column
        foo[, melt(tstrsplit(identity, "\\|")), by=.(name, number)][,
            #step 2: split by : to get count_number and total_number
            tstrsplit(value, ":"), by=.(name, number)][,
                #step 3: calculate ratio
                ratio := as.numeric(V3) / as.numeric(V2)],
        name + number ~ V1, value.var="ratio")
    

    输出:

          name number       bird       cat        cow       dog        fish       horse
    1:     Bob     37 0.02755906        NA 0.06583072        NA 0.005319149 0.071661238
    2:    Luna     23 0.02026432 0.2990354 0.03761755 0.1124031 0.024447950 0.001945525
    3: Melissa     33         NA        NA         NA        NA 0.569444444          NA
    

    以更一般的方式解决 OP 的评论: 在编码之前,您必须首先为您的问题设计一个解决方案。在您的脑海中想象您在解决方案的每个步骤中期望什么样的输出。然后让控制台成为您的助教,让文档成为您的讲师。

    例如在解决方案的第一步中,您按| 拆分,因此您在控制台中运行以下内容

    foo[, tstrsplit(identity, "|", fixed=TRUE)]
    

    您的期望是什么?你看到了什么?缺少namenumber?将它们添加到by=

    foo[, tstrsplit(identity, "|", fixed=TRUE), by=.(name, number)]
    

    那么,你得到了什么?错误?你能修好它吗?也许再次阅读文档?如果仍然无法解决,也许在网上搜索它?记住您要通过此步骤实现的目标:如何将其放入单个列中?也许您会发现如下内容:

    foo[, unlist(tstrsplit(identity, "|", fixed=TRUE)), by=.(name, number)]
    

    然后,继续下一步。

    【讨论】:

    • 感谢您的帮助!这太棒了。所以我学到了更多,你能解释一下你每一步都在做什么吗?
    猜你喜欢
    • 2020-08-29
    • 2018-10-23
    • 2018-10-23
    • 2018-09-20
    • 1970-01-01
    • 2012-04-07
    • 2019-05-14
    • 1970-01-01
    • 2020-08-24
    相关资源
    最近更新 更多