我想分析许多年的Quicken家庭财务记录。我将文件导出到qif并使用bank2csv程序渲染csv。在Quicken中,可以使用类别(例如汽车,税收),子类别(例如汽车:服务,汽车:燃料)和标签(例如自己,配偶,儿子)。 bank2csv将类别:subcategories / tag呈现为连接字符串。我想将类别放在子类列中的类别列子类别中,并在标记列中放置任何标记。我看到a similar question但是唉,strsplit
然后unlist
工作,然后索引每个元素,以便可以通过赋值将其写入正确的位置。这在这里不起作用,因为有时没有标签,有时没有子类别。将字符串拆分为列表并将该列表保存在列中非常容易,但实际上如何将列表的第一个元素分配给一个列,将第二个元素(如果存在)分配给第二列。当然有一种优雅简单的方式。
简化样本
library(data.table)
library(stringi)
dt <- data.table(category.tag=c("toys/David", "toys/David", "toys/James", "toys", "toys", "toys/James"), transaction=1:6)
如何创建第三列和第四列:category,tag。部分标记为NA
我可以做到以下但是它并没有让我走得太远。我需要一种方法来指定结果列表的第一个或第二个元素(而不是整个列表)
dt[, category:= strsplit(x = category.tag, split = "/") ]
答案 0 :(得分:6)
在 data.table v1.9.5 中推送了两个函数transpose()
和tstrsplit()
。
我们可以这样做:
require(data.table)
dt[, c("category", "tag") := tstrsplit(category.tag, "/", fixed=TRUE)]
# category.tag transaction category tag
# 1: toys/David 1 toys David
# 2: toys/David 2 toys David
# 3: toys/James 3 toys James
# 4: toys 4 toys NA
# 5: toys 5 toys NA
# 6: toys/James 6 toys James
tstrsplit
是transpose(strsplit(as.character(x), ...))
的包装器。您还可以传递fill=.
以使用NA
以外的任何其他值填充缺失值。
transpose()
也可用于列表,数据框和数据表。
答案 1 :(得分:4)
您可以使用cSplit
library(splitstackshape)
dt[, c("category", "tag") := cSplit(dt[,.(category.tag)], "category.tag", "/")]
dt
# category.tag transaction category tag
# 1: toys/David 1 toys David
# 2: toys/David 2 toys David
# 3: toys/James 3 toys James
# 4: toys 4 toys NA
# 5: toys 5 toys NA
# 6: toys/James 6 toys James
答案 2 :(得分:2)
1)尝试read.table
read <- function(x) read.table(text = x, sep = "/", fill = TRUE, na.strings = "")
dt[, c("category", "tag") := read(category.tag)]
不需要额外的包裹。
2)另一种方法是在tidyr包中使用separate
:
library(tidyr)
separate(dt, category.tag, c("category", "tag"), extra = "drop")
以上是来自github的tidyr版本0.1.0.9000。要安装它,请确保已安装devtools R软件包并发出命令:devtools::install_github("hadley/tidyr")
。
更新:注册Richard Scrivens&#39;评论和小改进。添加了泰迪尔解决方案。
答案 3 :(得分:1)
由于您已经加载了“stringi”,您还可以查看stri_split_fixed
和simplify
参数:
setnames(cbind(dt, stri_split_fixed(dt$category.tag, "/", simplify = TRUE)),
c("V1", "V2"), c("category", "tag"))[]
# category.tag transaction category tag
# 1: toys/David 1 toys David
# 2: toys/David 2 toys David
# 3: toys/James 3 toys James
# 4: toys 4 toys NA
# 5: toys 5 toys NA
# 6: toys/James 6 toys James
虽然我必须承认我偏爱cSplit
: - )