我有一个包含这些键值对的字符串,我想从它构造数据框,
s="{'#JJ': 121, '#NN': 938, '#DT': 184, '#VB': 338, '#RB': 52}"
r1<-sapply(strsplit(s, "[^0-9_]+",as.numeric),as.numeric)
r2<-sapply(strsplit(s, "[^A-Z]+",as.numeric),as.character)
d<-data.frame(id=r2,value=r1)
是什么赋予:
r1
[,1]
[1,] NA
[2,] 121
[3,] 938
[4,] 184
[5,] 338
[6,] 52
r2
[,1]
[1,] ""
[2,] "JJ"
[3,] "NN"
[4,] "DT"
[5,] "VB"
[6,] "RB"
d
id value
1 NA
2 JJ 121
3 NN 938
4 DT 184
5 VB 338
6 RB 52
首先我想在使用正则表达式后没有NA和“”。我认为它应该像{2,}意思匹配所有来自第二次出现,但我不能在R中这样做。
我想做的另一个想法是:拥有一个如下所示的数据框:
m
1 {'#JJ': 121, '#NN': 938, '#DT': 184, '#VB': 338, '#RB': 52}
2 {'#NN': 168, '#DT': 59, '#VB': 71, '#RB': 5, '#JJ': 35}
3 {'#JJ': 18, '#NN': 100, '#DT': 23, '#VB': 52, '#RB': 11}
4 {'#NN': 156, '#JJ': 39, '#DT': 46, '#VB': 67, '#RB': 21}
5 {'#NN': 112, '#DT': 39, '#VB': 57, '#RB': 8, '#JJ': 32}
6 {'#DT': 236, '#NN': 897, '#VB': 420, '#RB': 122, '#JJ': 240}
7 {'#NN': 316, '#RB': 25, '#DT': 66, '#VB': 112, '#JJ': 81}
8 {'#NN': 198, '#DT': 29, '#VB': 85, '#RB': 37, '#JJ': 44}
9 {'#RB': 30}
10 {'#NN': 373, '#DT': 48, '#VB': 71, '#RB': 21, '#JJ': 36}
11 {'#NN': 49, '#DT': 17, '#VB': 23, '#RB': 11, '#JJ': 8}
12 {'#NN': 807, '#JJ': 135, '#DT': 177, '#VB': 315, '#RB': 69}
我想迭代每一行,并将数值分成键所指定的列。
显示几行的示例,我希望它如何:
答案 0 :(得分:4)
我会使用解析JSON的东西,你的数据似乎是:
s <- "{'#JJ': 121, '#NN': 938, '#DT': 184, '#VB': 338, '#RB': 52}"
parse.one <- function(s) {
require(rjson)
v <- fromJSON(gsub("'", '"', s))
data.frame(id = gsub("#", "", names(v)),
value = unlist(v, use.names = FALSE))
}
parse.one(s)
# id value
# 1 JJ 121
# 2 NN 938
# 3 DT 184
# 4 VB 338
# 5 RB 52
对于问题的第二部分,我会通过parse.one
传递lapply
函数的略微修改版本,然后让plyr的rbind.fill
函数将这些部分对齐,同时填充缺失的值与NA
:
df <- data.frame(m = c(
"{'#JJ': 121, '#NN': 938, '#DT': 184, '#VB': 338, '#RB': 52}",
"{'#NN': 168, '#DT': 59, '#VB': 71, '#RB': 5, '#JJ': 35}",
"{'#JJ': 18, '#NN': 100, '#DT': 23, '#VB': 52, '#RB': 11}",
"{'#JJ': 12, '#VB': 5}"
))
parse.one <- function(s) {
require(rjson)
y <- fromJSON(gsub("'", '"', s))
names(y) <- gsub("#", "", names(y))
as.data.frame(y)
}
library(plyr)
rbind.fill(lapply(df$m, parse.one))
# JJ NN DT VB RB
# 1 121 938 184 338 52
# 2 35 168 59 71 5
# 3 18 100 23 52 11
# 4 12 NA NA 5 NA
答案 1 :(得分:2)
目前,我将为您问题的第一部分提供解决方案。清理字符串并使用read.table
:
s="{'#JJ': 121, '#NN': 938, '#DT': 184, '#VB': 338, '#RB': 52}"
read.table(text = gsub(",", "\n", gsub("[{|}|#]", "", s)),
header = FALSE, sep = ":", strip.white=TRUE)
# V1 V2
# 1 JJ 121
# 2 NN 938
# 3 DT 184
# 4 VB 338
# 5 RB 52
对于第二部分,这是另一种使用我写的名为“splitstackshape”的包中的concat.split
的替代方法:
示例数据:
df <- data.frame(m = c(
"{'#JJ': 121, '#NN': 938, '#DT': 184, '#VB': 338, '#RB': 52}",
"{'#NN': 168, '#DT': 59, '#VB': 71, '#RB': 5, '#JJ': 35}",
"{'#JJ': 18, '#NN': 100, '#DT': 23, '#VB': 52, '#RB': 11}"
))
与上面类似的清理,再加上“id”列。
df$m <- gsub("[{|}|#]", "", df$m)
df$id <- 1:nrow(df)
加载“splitstackshape”包:
# install.packages("splitstackshape")
library(splitstackshape)
df2 <- concat.split(concat.split.multiple(df, "m", ",", "long"),
"m", ":", drop = TRUE)
## df2 <- df2[complete.cases(df2), ] ##
## ^^ might be necessary if there are NAs in the resulting data.frame
数据现在采用易于操作的“长”格式:
df2
# id time m_1 m_2
# 1 1 1 JJ 121
# 2 2 1 NN 168
# 3 3 1 JJ 18
# 4 1 2 NN 938
# 5 2 2 DT 59
# 6 3 2 NN 100
# 7 1 3 DT 184
# 8 2 3 VB 71
# 9 3 3 DT 23
# 10 1 4 VB 338
# 11 2 4 RB 5
# 12 3 4 VB 52
# 13 1 5 RB 52
# 14 2 5 JJ 35
# 15 3 5 RB 11
以下是使用“reshape2”软件包中的dcast
操作数据的示例:
library(reshape2)
dcast(df2, id ~ m_1, value.var="m_2")
# id DT JJ NN RB VB
# 1 1 184 121 938 52 338
# 2 2 59 35 168 5 71
# 3 3 23 18 100 11 52