我希望从数据中创建一个查找表,其中列(user_entry
)中的条目采用不同的格式,每行可能包含多个实例。
# create example dataframe.
id <- c(1111,1112,1113,1114)
user_entry <- c("999/1001","1002;1003","999/1004\n999/1005","9991006 9991007")
df <- data.frame(id,user_entry)
> df
id user_entry
1 1111 999/1001
2 1112 1002;1003
3 1113 999/1004\n999/1005
4 1114 9991006 9991007
我只对4位数代码感兴趣,这些代码可能有也可能没有3位数的位置代码和/或分隔符,例如&#34; /&#34;或空间。每个条目中可能有多个4位数代码,我想在最终查找表中单独列出每个代码(参见下面的lookup
)。
下面的代码完成了我正在寻找的内容,但是内部循环和数据框内部的循环非常不优雅。有没有更简洁的方法来做到这一点?
library(dplyr);library(stringr)
# use stringr package to extract only digits
df <- df %>%
mutate(entries = str_extract_all(user_entry,"[[:digit:]]+")) %>%
select(-user_entry)
# initialise lookup dataframe
lookup <- df[FALSE,]
for (record in 1:nrow(df)){
entries <- df$entries[[record]]
for (element in 1:length(entries)){
# only interested in 4 digit codes
if (nchar(entries[element])>3){
# remove 3 digit code if it is still attached
lookup_entry <- gsub('.*?(\\d{4})$','\\1',entries[element])
lookup <- rbind(lookup,data.frame(id=df$id[[record]],entries=lookup_entry))
}
}
}
> lookup
id entries
1 1111 1001
2 1112 1002
3 1112 1003
4 1113 1004
5 1113 1005
6 1114 1006
7 1114 1007
答案 0 :(得分:2)
使用基数R,
matches <- regmatches(user_entry, gregexpr("(\\d{4})\\b", user_entry))
data.frame(
id = rep(id, lengths(matches)),
entries = unlist(matches),
stringsAsFactors = FALSE
)
# id entries
# 1 1111 1001
# 2 1112 1002
# 3 1112 1003
# 4 1113 1004
# 5 1113 1005
# 6 1114 1006
# 7 1114 1007
答案 1 :(得分:0)
不是很优雅,但我认为它适用于你的情况:
library("tidyverse")
df1 <- df %>%
separate_rows(user_entry, sep = '(/|;|\\n|\\s)')
extract <- str_extract(df1$user_entry,"(?=\\d{3})\\d{4}$")
df1$extract <- extract
df2 <- df1[!is.na(df1$extract),]
df2
> df2
id user_entry extract
#1111 1001 1001
#1112 1002 1002
#1112 1003 1003
#1113 1004 1004
#1113 1005 1005
#1114 9991006 1006
#1114 9991007 1007