对于示例数据框:
df <- structure(list(ID = 1:6, region = structure(c(5L, 3L, 1L, 4L,
6L, 2L), .Label = c("AB1", "AB22", "AC225", "AF32", "AX11", "OI222"
), class = "factor"), level = c(2L, 3L, 1L, 2L, 3L, 2L)), .Names = c("ID",
"region", "level"), class = "data.frame", row.names = c(NA, -6L
))
我有一个名为region的列,其中至少有两个字符变量,然后是1,2或3个数字变量。级别变量表示该区域的大小(其中级别1表示国家中的最大区域,级别3包含最小区域)。
区域代码不仅详细说明每个ID所指的区域,而且还经常(如果适用)更大的链接区域。
例如,AC225是: 区域0的AC;区域1中的AC2;区域2中的AC22;区域3中的AC225。
我希望使用区域代码为每个ID变量执行此操作。对于某些ID,事情稍微复杂一点,我不会知道区域2或3(然后我希望添加NA)。例如,对于AB32,我希望AB为region.0,AB3为region.1,AB32为region.2,NA为region.3。
我尝试使用stringr函数,但没有取得多大成功:
library(stringr)
df$region.0 <- str_sub(df$region,1,2)
df$region.1 <- str_sub(df$region,1,2,3)
df$region.2 <- str_sub(df$region,1,2,3,4)
df$region.3 <- str_sub(df$region,1,2,3,4,5)
如果有人能帮助我,我将非常感激。
答案 0 :(得分:3)
也许可以尝试使用stringi
和regex
:
library("stringi")
df$region.0 <- stri_extract_all_regex(df$region, "^..")
df$region.1 <- stri_extract_all_regex(df$region, "^...")
df$region.2 <- stri_extract_all_regex(df$region, "^....")
df$region.3 <- stri_extract_all_regex(df$region, "^.....")
> df
ID region level region.0 region.1 region.2 region.3
1 1 AX11 2 AX AX1 AX11 NA
2 2 AC225 3 AC AC2 AC22 AC225
3 3 AB1 1 AB AB1 NA NA
4 4 AF32 2 AF AF3 AF32 NA
5 5 OI222 3 OI OI2 OI22 OI222
6 6 AB22 2 AB AB2 AB22 NA
答案 1 :(得分:1)
另一种方式,来自基地R的gsub
和mapply
。
数字之前的大写字母数量并不重要,它避免了必须键入的行数与#34; new&#34;要添加的列:
maxlevel <- 3 # you can have more later if you wish to
res <- cbind(df,
`colnames<-`(t(mapply(function(x, y){
c(gsub("^([A-Z]+)\\d+$", "\\1", x),
sapply(1:y,
function(n){
gsub(paste0("^([A-Z]+\\d{",n,"})\\d*$"), "\\1", x)}),
rep(NA, maxlevel-y))},
df$region, df$level)),
paste("region", 0:maxlevel, sep=".")))
res
# ID region level region.0 region.1 region.2 region.3
#1 1 AX11 2 AX AX1 AX11 <NA>
#2 2 AC225 3 AC AC2 AC22 AC225
#3 3 AB1 1 AB AB1 <NA> <NA>
#4 4 AF32 2 AF AF3 AF32 <NA>
#5 5 OI222 3 OI OI2 OI22 OI222
#6 6 AB22 2 AB AB2 AB22 <NA>
<强> 解释 强>
mapply
获取区域和级别的名称来计算一个向量,该向量仅包含区域名称的字母,字母以及从1到level
的数字最后NA
到达等于maxlevel
的长度。