我有一个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。)
答案 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)]
您的期望是什么?你看到了什么?缺少name
和number
?将它们添加到by=
中。
foo[, tstrsplit(identity, "|", fixed=TRUE), by=.(name, number)]
然后,您会得到什么?错误?你能修好它吗?也许再次阅读文档?如果仍然无法解决,也许可以在线搜索?记住这一步要实现的目标:如何将其放入单个列?也许您会发现以下内容:
foo[, unlist(tstrsplit(identity, "|", fixed=TRUE)), by=.(name, number)]
然后,继续下一步。