2017-10-20 16 views
2

私は長いベクトルを持っています。各要素は文字列です。 各文字列は、 '、'で区切られた部分文字列に分割できます。R長い文字列内の部分文字列を新しい部分文字列で置き換える方法

私のベクトルの各文字列に少なくとも1つの「不良」文字列が含まれているかどうかをチェックしたいと思います。そうであれば、その '不良'文字列を含むSUBstring全体を新しい文字列に置き換える必要があります。私は長い関数をループで書いた。しかし、私は簡単な方法でなければならないと誓ってもいいでしょう。 ありがとうございました!

# 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

良いアイデアだが、これは私を助けるつもりはない。私は良いストリングに参加したくありません。私は、新しい部分文字列を含む不正な文字列を含むWHOLE部分文字列を置き換えたいです。 – 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

私は分割征服の方法でそれを行いました。最初に、1つの文字列の操作だけを行い、それをベクトル化する関数を作成しました。基本的には

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

はここtidyversepurrr、およびstringrを使用したアプローチだそのリスト上で、リストにマップ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

関連する問題