我有一个非常大的数据数组:
'data.frame': 40525992 obs. of 14 variables:
$ INSTNM : Factor w/ 7050 levels "A W Healthcare Educators"
$ Total : Factor w/ 3212 levels "1","10","100",
$ Crime_Type : Factor w/ 72 levels "MURD11","NEG_M11",
$ Count : num 0 0 0 0 0 0 0 0 0 0 ...
Crime_Type列包含犯罪类型和年份,因此“MURD11”是2011年的谋杀案。这些是我孩子正在为她的学校项目分析的大学校园犯罪统计数据,我在她被困时正在帮助。我目前只是在创建一个她可以分析的干净数据文件
一旦我使用'gather'将宽文件(列中的所有犯罪类型'9')转换为长文件,文件大小将从300MB变为 8 GB。我正在工作的文件on是8GB。你是那个问题吗?如何将其转换为data.table以加快处理速度?
我想要做的是将split
这个'Crime_Type'列分为两列'Crime_Type'和'Year'。数据包含字母数字和数字。还有一些像NEG_M这样的特殊角色是“疏忽的杀人”。
我们稍后会更换全名,但有人可以建议我如何分开
MURD11 - > MURD和11(两列) NEG_M10 - > NEG_M和10(两列)
等...
我尝试过使用,
df <- separate(totallong, Crime_Type, into = c("Crime", "Year"), sep = "[:digit:]", extra = "merge")
df <- separate(totallong, Crime_Type, into = c("Year", "Temp"), sep = "[:alpha:]", extra = "merge")
第一个将犯罪分开,因为它寻找数字。第二个根本不起作用。
我也试过
df$Crime_Type<- apply (strsplit(as.character(df$Crime_Type), split="[:digit:]"))
这根本不起作用。我已经浏览了很多关于堆栈溢出的帖子,这就是我得到这些命令的地方,但我现在真的被困住了,非常感谢你的帮助。
答案 0 :(得分:2)
由于您已经使用tidyr
(由separate
证明),请尝试extract
函数,在给定正则表达式的情况下,将每个捕获的组放入新列。 'Crime_Type'是所有非数字的东西,'Year'是数字的东西。相应地调整正则表达式。
library(tidyr)
extract(df, 'Crime_Type', into=c('Crime', 'Year'), regex='^([^0-9]+)([0-9]+)$')
答案 1 :(得分:1)
在base R
中,一个选项是在非数字和数字部分之间创建唯一的分隔符。我们可以将非数字([^0-9]+
)和数字([0-9]+
)字符包装在括号((..)
)内,并在替换中使用{{1} }对于第一个捕获组,后跟\\1
和第二个组(,
)。这可以用作\\2
的输入向量,read.table
读取为两列。
sep=','
如果需要,我们可以 df1 <- read.table(text=gsub('([^0-9]+)([0-9]+)', '\\1,\\2',
totallong$Crime_Type),sep=",", col.names=c('Crime', 'Year'))
df1
# Crime Year
#1 MURD 11
#2 NEG_M 11
使用原始数据集
cbind
或者在cbind(totallong, df1)
中,我们可以base R
使用strsplit
指定非数字(split
)和数字((?<=[^0-9])
)之间的边界。在这里,我们使用(?=[0-9])
来匹配边界。输出为lookarounds
,我们可以list
rbind
个元素list
并将其转换为do.call(rbind
data.frame
或另一个选项是来自as.data.frame(do.call(rbind, strsplit(as.character(totallong$Crime_Type),
split="(?<=[^0-9])(?=[0-9])", perl=TRUE)))
# V1 V2
#1 MURD 11
#2 NEG_M 11
的开发版本的tstrsplit
,即。 data.table
。在这里,我们使用相同的v1.9.5
。此外,还可以选择将输出列转换为不同的regex
。
class
如果我们不需要&#39; Crime_Type&#39;在输出中的列,可以将其分配给library(data.table)#v1.9.5+
setDT(totallong)[, c('Crime', 'Year') := tstrsplit(Crime_Type,
"(?<=[^0-9])(?=[0-9])", perl=TRUE, type.convert=TRUE)]
# Crime_Type Crime Year
#1: MURD11 MURD 11
#2: NEG_M11 NEG_M 11
NULL
注意:安装devel版本的说明是here
或者,在将行折叠为单个字符串(&#39; v2&#39;)之后,来自totallong[, Crime_Type:= NULL]
的{{1}}更快的选项。 &#39; v3&#39;中的替代元素可以通过使用stri_extract_all
建立索引来提取,以创建新的library(stringi)
seq
data.frame
library(stringi)
v2 <- paste(totallong$Crime_Type, collapse='')
v3 <- stri_extract_all(v2, regex='\\d+|\\D+')[[1]]
ind1 <- seq(1, length(v3), by=2)
ind2 <- seq(2, length(v3), by=2)
d1 <- data.frame(Crime=v3[ind1], Year= v3[ind2])