我有一个不规则结构的字符数据向量,我想从中找到提取特定数字。例如,拿一个更大的数据集:
x <- c("2001 Tax @ $25.19/Widget, 2002 Est Tax @ $10.68/Widget; 2000 Est Int @ $55.67/Widget",
"1999 Tax @ $81.16/Widget",
"1998 Tax @ $52.72/Widget; 2001 Est Int @ $62.49/Widget",
"1994 Combined Tax/Int @ $68.33/widget; 1993 Est Int @ $159.67/Widget",
"1993 Combined Tax/Int @ $38.33/widget; 1992 Est Int @ $159.67/Widget",
"2006 Tax @ $129.21/Widget, 1991 Est Tax @ $58.19/Widget; 1991 Est Int @ $30.95/Widget")
等等。阅读表格以获得更大的矢量显示大多数条目用分号或逗号分隔,并且只使用有限数量的术语 - 年份,税收,国际合作,合并,预计 - 偶尔会有变化在条目中(如“;”与“,”或“小部件”与“小部件”)。
我想将与上述术语相关的每个数字提取到更结构化的数据表中,例如:
[id] [year] [number] [cat] [est]
row1 2001 25.19 Tax
row1 2002 10.68 Tax Est
row1 2000 55.67 Int Est
row2 1999 81.16 Tax
row3 1998 52.72 Tax
row3 2001 62.49 Int Est
....
或者可能是更紧凑/稀疏的表示,如:
[id] [1999tax] [2001tax] [2002esttax] [2000estint]
row1 0 25.19 10.68 55.67
row2 81.16 0 0 0
如果这是有道理的 - 我最终需要将其纳入回归模型。
我的第一种方法是编写以下伪代码:
到目前为止,我只是走得很远:
pieces.of.x <- strsplit(x1, "[;,]"); head(pieces.of.x)
给出:
[[1]]
[1] "2001 Tax @ $25.19/Widget" " 2002 Est Tax @ $10.68/Widget" " 2000 Est Int @ $55.67/Widget"
[[2]]
[1] "1999 Tax @ $81.16/Widget"
[[3]]
[1] "1998 Tax @ $52.72/Widget" " 2001 Est Int @ $62.49/Widget"
[[4]]
[1] "1994 Combined Tax/Int @ $68.33/widget" " 1993 Est Int @ $159.67/Widget"
[[5]]
[1] "1993 Combined Tax/Int @ $38.33/widget" " 1992 Est Int @ $159.67/Widget"
[[6]]
[1] "2006 Tax @ $129.21/Widget" " 1991 Est Tax @ $58.19/Widget" " 1991 Est Int @ $30.95/Widget"
不幸的是,我没有R中的lapply()和正则表达式(“regex”)的知识,以创建一个足够强大的过程来提取年份,对元素的每个子向量进行操作,然后归还他们。
提前感谢您阅读。
答案 0 :(得分:2)
这类似于其他答案之一,并区分行号(您的[id]列)。
matches <- regmatches(x,gregexpr("[0-9]{4} [^@]+@ \\$[0-9.]+",x))
lengths <- sapply(matches,length)
z <- unlist(matches)
z <- regmatches(z,regexec("([0-9]{4}) ([^@]+) @ \\$([0-9.]+)",z))
df <- t(sapply(z,function(x)c(year=x[2], number=x[4], cat=x[3])))
df <- data.frame(id=rep(1:length(x),times=lengths),df, stringsAsFactors=F)
df$est <- ifelse(grepl("Est",df$cat),"Est","")
df$cat <- regmatches(df$cat,regexpr("[^ /]+$",df$cat))
df
# id year number cat est
# 1 1 2001 25.19 Tax
# 2 1 2002 10.68 Tax Est
# 3 1 2000 55.67 Int Est
# 4 2 1999 81.16 Tax
# 5 3 1998 52.72 Tax
# 6 3 2001 62.49 Int Est
# 7 4 1994 68.33 Int
# 8 4 1993 159.67 Int Est
# 9 5 1993 38.33 Int
# 10 5 1992 159.67 Int Est
# 11 6 2006 129.21 Tax
# 12 6 1991 58.19 Tax Est
# 13 6 1991 30.95 Int Est
答案 1 :(得分:2)
在处理字符串时,stringr包非常有用,我打赌有人甚至可以创建一个匹配器来提取命名捕获组以获得类似的解决方案......
[编辑:错过了合并的条目]
library(stringr)
library(data.table)
# Split the row entries
x <- strsplit(x, "[,;]")
# Generate the entry identifiers.
i <- 0
id <- unlist( sapply( x, function(r) rep(i<<-i+1, length(r) ) ) )
# Extract the desired values
x <- unlist( x, recursive = FALSE )
year.re <- "(^\\s?([[:digit:]]{4})\\s)"
value.re <- "[$]([[:digit:]]+[.][[:digit:]]{2})[/]"
object.re <- "[/]([[:alnum:]]+)$"
Cats<- c("Tax","Int","Combination")
x <- lapply( x, function(str) {
c( Year=str_extract( str, year.re),
Category=Cats[ grepl( "Tax", str)*1 + grepl( "Int", str)*2 ],
Estimate=grepl( "Est", str),
Value=str_match( str, value.re)[2],
Object=str_match( str, object.re)[2] )
})
# Create a data object.
data.table( ID=id, do.call(rbind,x), key=c("Year") )
## ID Year Category Estimate Value Object
## 1: 6 1991 Tax TRUE 58.19 Widget
## 2: 6 1991 Int TRUE 30.95 Widget
## 3: 5 1992 Int TRUE 159.67 Widget
## 4: 4 1993 Int TRUE 159.67 Widget
## 5: 5 1993 Combination FALSE 38.33 widget
## 6: 4 1994 Combination FALSE 68.33 widget
## 7: 3 1998 Tax FALSE 52.72 Widget
## 8: 2 1999 Tax FALSE 81.16 Widget
## 9: 1 2000 Int TRUE 55.67 Widget
## 10: 3 2001 Int TRUE 62.49 Widget
## 11: 1 2001 Tax FALSE 25.19 Widget
## 12: 1 2002 Tax TRUE 10.68 Widget
## 13: 6 2006 Tax FALSE 129.21 Widget
答案 2 :(得分:1)
要准确创建您要求的数据框,您可以使用一些技巧,例如strsplit
,正则表达式和rbind
。
x <- unlist(strsplit(x, ',|;'))
bits <- regmatches(x,gregexpr('(\\d|\\.)+|(Tax|Int|Est)', x))
df <- do.call(rbind, lapply(bits, function(info) {
data.frame(year = info[[1]], number = tail(info, 1)[[1]],
cat = if ('Tax' %in% info) 'Tax' else 'Int',
est = if ('Est' %in% info) 'Est' else '')
}))
df$cat <- factor(df$cat); df$est <- factor(df$est);
给了我们
year number cat est
1 2001 25.19 Tax
2 2002 10.68 Tax Est
3 2000 55.67 Int Est
4 1999 81.16 Tax
5 1998 52.72 Tax
答案 3 :(得分:0)
您可以使用以下方式提取数字:
regmatches(x,gregexpr('(\\d)+', x))
产生
[[1]]
[1] "2001" "25.19" "2002" "10.68" "2000" "55.67"
[[2]]
[1] "1999" "81.16"
[[3]]
[1] "1998" "52.72" "2001" "62.49"
[[4]]
[1] "1994" "68.33" "1993" "159.67"
[[5]]
[1] "1993" "38.33" "1992" "159.67"
[[6]]
[1] "2006" "129.21" "1991" "58.19" "1991" "30.95"
但是,如果您认为每年的信息由,
或;
分隔,请尝试以下操作:
x <- unlist(strsplit(x, ',|;'))
nums <- regmatches(x,gregexpr('(\\d|\\.)+', x))
df <- data.frame(matrix(as.numeric(unlist(nums)), ncol = 2, byrow = TRUE))
colnames(df) <- c('Year', 'Number')
看起来像
Year Number
1 2001 25.19
2 2002 10.68
3 2000 55.67
4 1999 81.16
5 1998 52.72