如何使用R data.table / data.frame将长字符串拆分/解析为表格数据?

时间:2018-10-22 23:30:29

标签: r parsing dataframe data.table

我有一个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。)

1 个答案:

答案 0 :(得分:3)

在计算比率并重塑为所需的格式之前,您可以先用|分割,然后再用:分割。

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)]

然后,继续下一步。