2017-10-20 3 views
2

긴 벡터가 있습니다. 각 요소는 문자열입니다. 각 문자열은 ','로 구분 된 부분 문자열로 나눌 수 있습니다.R 긴 문자열의 하위 문자열을 새 하위 문자열로 바꾸는 방법

내 벡터의 각 문자열에 적어도 하나의 '잘못된'문자열이 포함되어 있는지 확인하고 싶습니다. 그렇다면 '나쁜'문자열을 포함하는 전체 SUBstring을 새 문자열로 바꿔야합니다. 루프가있는 긴 함수를 작성했습니다. 그러나 나는 그것을하기위한 더 쉬운 방법이 있어야한다고 맹세 할 수있다. 아마도 stringr을 사용했을 것이다. 조언 해 주셔서 감사합니다.

# Create an example data frame: 
test <- data.frame(a = c("str1_element_1_aaa, str1_element_2", 
         "str2_element_1", 
         "str3_element_1, str3_element_2_aaa, str3_element_3"), 
        stringsAsFactors = F) 
test 
str(test) 

# Defining my long function that checks if each string in a 
# vector contains a substring with a "bad" string in it. 
# If it does, that whole substring is replaced with a new string: 
library(stringr) 
mystring_replace = function(strings_vector, badstring, newstring){ 
    with_string <- grepl(badstring, strings_vector) # what elements contain badstring? 
    mysplits <- str_split(string = test$a[with_string], pattern = ', ') # split those elements with badstring based on ', ' 
    for (i in 1:length(mysplits)) { # loop through the list of splits: 
    allstrings <- mysplits[[i]] 
    for (ii in 1:length(allstrings)) { # loop through substrings 
     if (grepl(badstring, allstrings[ii])) mysplits[[i]][ii] <- newstring 
    } 
    } 
    for (i in seq_along(mysplits)) { # merge the split elements back together 
    mysplits[[i]] <- paste(mysplits[[i]], collapse = ", ") 
    } 
    strings_vector[with_string] <- unlist(mysplits) 
    return(strings_vector) 
} 
# Test 
mystring_replace(test$a, badstring = '_aaa', newstring = "NEW") 
+0

대신 3 개의 for 루프를 사용하면 잘못된 문자열로 나뉘어 좋은 문자열에 가입 할 수 있습니다. – numbtongue

+0

좋은 생각이긴하지만 이것은 나에게 도움이되지 않습니다. 나는 좋은 끈에 합류하고 싶지 않다. 잘못된 하위 문자열이 포함 된 전체 하위 문자열을 바꾸고 싶습니다. – user3245256

답변

1

생각해보십시오.

new_str_replace <- function(strings_vector, badstring, newstring){ 
    split.dat <- strsplit(strings_vector,', ')[[1]] 
    split.dat[grepl(badstring, split.dat)] <- newstring 
    return(paste(split.dat, collapse = ', ')) 
} 

results <- unname(sapply(test$a, new_str_replace, badstring = '_aaa', newstring = 'NEW')) 
results 
#[1] "NEW, str1_element_2"     "str2_element_1"      
#[3] "str3_element_1, NEW, str3_element_3" 
1

나는 divide-an-conquer 방식으로했습니다. 먼저 하나의 문자열에 대해서만 연산을 수행 한 다음 벡터화했습니다. 기본적으로

library(tidyverse) 
library(stringr) 

# Small utility function 
find_and_replace <- function(string, bad_string, replacement_string) { 
    ifelse(str_detect(string, bad_string), replacement_string, string) 
} 

str_split(test$a, ", ") %>%     
    map(find_and_replace, "aaa", "NEW") %>% 
    map_chr(paste, collapse = ", ") %>% 
    unlist 

:

# does the operation for a string only. divide-and-conquer 
replace_one = function(string, badstring, newstring) { 
    # split it at ", " 
    strs = str_split(string, ", ")[[1]] 
    # an ifelse to find the ones containing badstring and replacing them 
    strs = ifelse(grepl(badstring, strs, fixed = TRUE), newstring, strs) 
    # join them again 
    paste0(strs, collapse = ", ") 
} 

# vectorizes it 
my_replace = Vectorize(replace_one, "string", USE.NAMES = FALSE) 
1

다음은 tidyverse, purrrstringr를 사용하는 접근 방식이 목록을 통해,리스트로지도 find_and_replace를 벡터를 분할하고, 그 결과를 축소합니다. 나는 각 파이프 %>% 후 결과를 개별적으로 보는 것이 좋습니다.

+0

나는 그것을 사랑한다! 아름다운! 고맙습니다! – user3245256

+0

이상한, 나는 함수에 넣어하지만 제대로 작동하지 않습니다 : find_and_replace < – user3245256

+0

# 작은 유틸리티 함수 - 함수 (문자열, bad_string, replacement_string) { ifelse (bad_string str_detect (문자열), replacement_string, 문자열) } # 기능 : string_replace_n <- 기능 (mystring에, mybad_string, myreplacement) { 아웃 <- str_split (mystring에, "") %> % 맵 (find_and_replace, mybad_string, myreplacement) %> % map_chr (페이스트 붕괴 = ",") %> % unlist out } – user3245256