2017-04-18 2 views
1

열 (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 

는 I 또는 "/"또는 공간으로서 3 자리 위치 코드 및/또는 구분 문자로 시작되지 않을 수있다 4 자리 코드에만 관심이다. 각 항목에는 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

어쩌면 당신은 단지 각 숫자의 마지막 4 자리 숫자를 추출 할 수 있습니다 순서? ['str_extract_all (user_entry, "\\ d {4} \\ b")'] (https://regex101.com/r/Hm20nm/1)? –

답변

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 
+0

이것은 우리가 4 자리 숫자 앞에 항상 999를 가졌다 고 가정합니다. 나는 그것이 항상 사실 일지 모르겠다. 마지막 항목이 1007999이면 정규식은 7999를 반환합니다. – Kristofersen

+0

그 외에는 훨씬 깔끔한 해결책입니다. 내가 이익을 위해 그것을 게시 할 것 인 것을 상상하는 것은 이익을 얻는다. 정확히 999를 처리하기를 원하는지 확실하지 않습니다. – Kristofersen

+0

패턴에 따라 (예 : "999"에 관계없이) 관심있는 4 자리 코드는 항상 오른쪽에 한정되어 있으므로 예제를 들어 보면 충분합니다. SO에 대한 질문을 "최소/재현 가능"으로 줄일 위험은 다양성이 충분하지 않은 경우 지나치게 단순화됩니다. \ * shrug \ * – r2evans

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