5

Rの文字列内の特定の位置にある文字を削除する方法を探しています。たとえば、文字列がある場合"1,2,1,1,2,1,1,1,1,2,1,1"、3番目、4番目、7番目、8番目の位置を削除したいと思います。この操作により、文字列が作成されます"1,1,2,1,1,1,1,2,1,1"

残念ながら、strsplitを使用して文字列をリストに分割することはできません。これは、私が使用している文字列の長さが100万文字を超えているためです。私が約2,500本の弦を持っていることを考えると、かなりの時間がかかることがわかります。

あるいは、文字を空の文字列に置き換える方法を見つけること""も同じ目的を達成すると思います。この考え方を調べて、私はこのStackOverflowの投稿に出くわしました:

R:文字列内の5番目の要素を置き換えるにはどうすればよいですか?

残念ながら、提案された解決策を効率的に一般化することは困難であり、2000の位置のリストを削除するには、入力文字列ごとに約60秒かかります。

subchar2 = function(inputstring, pos){
string = ""
memory = 0
for(num in pos){
    string = paste(string, substr(inputstring, (memory+1), (num-1)), sep = "")
    memory = num
}
string = paste(string, substr(inputstring,(memory+1), nchar(inputstring)),sep = "")
return(string)
}

問題を調べてみると、特定の位置の文字が"-"次のように置き換えられているように見えるコードのスニペットが見つかりました。

subchar <- function(string, pos) {
        for(i in pos) {
            string <- gsub(paste("^(.{", i-1, "}).", sep=""), "\\1-", string)
        }
        return(string)
}

私は正規表現を(まだ)完全には理解していませんが、これらの線に沿った何かが最初のコードソリューションよりも時間的にはるかに優れているのではないかと強く疑っています。残念ながら、このsubchar関数は、posの値が高くなると機能しなくなるようです。

> test = subchar(data[1], 257)
Error in gsub(paste("^(.{", i - 1, "}).", sep = ""), "\\1-", string) :
invalid regular expression '^(.{256}).', reason 'Invalid contents of {}'

SQLを使用して文字列データをテーブルに読み込むことも検討していましたが、洗練された文字列ソリューションがあることを期待していました。これを行うためのRでのSQL実装は、かなり複雑に思えます。

何か案は?ありがとう!

4

3 に答える 3

3

を使用してそれらを読んでくださいscan()。区切り文字を「、」および「what="a」に設定できます。scan一度に1つの「行」を使用できnlines=1、それがの場合textConnection、「パイプライン」は最後に読み取った時点の場所を「記憶」します。

x <- paste( sample(0:1, 1000, rep=T), sep=",")
xin <- textConnection(x)

x995 <- scan(xin, sep=",", what="a", nmax=995)
# Read 995 items
x5 <- scan(xin, sep=",", what="a", nmax=995)
# Read 5 items

これが5本の「線」のイラストです

> x <- paste( rep( paste(sample(0:1, 50, rep=T), collapse=","),  5),  collapse="\n")
> str(x)
 chr "1,0,0,0,0,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1,0,0,1,0,1,0,1,0,0,1,0,0,0,1,0,1,0,0,1,1,1,1,1,0,0,0,1,0,0\n1,0,0,0,0,1,0,0,1,1,1,0,1,"| __truncated__
> xin <- textConnection(x)
> x1 <- scan(xin, sep=",", what="a", nlines=1)
Read 50 items
> x2 <- scan(xin, sep=",", what="a", nlines=1)
Read 50 items
> x3 <- scan(xin, sep=",", what="a", nlines=1)
Read 50 items
> x4 <- scan(xin, sep=",", what="a", nlines=1)
Read 50 items
> x5 <- scan(xin, sep=",", what="a", nlines=1)
Read 50 items
> x6 <- scan(xin, sep=",", what="a", nlines=1)
Read 0 items
> length(x1)
[1] 50
> length(x1[-c(3,4,7,8)])
[1] 46
> paste(x1, collapse=",")
[1] "1,0,0,0,0,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1,0,0,1,0,1,0,1,0,0,1,0,0,0,1,0,1,0,0,1,1,1,1,1,0,0,0,1,0,0"
> 
于 2012-08-21T01:23:05.167 に答える
3

strsplitを使用すると、10倍以上高速になりますfixed = TRUE。大まかな外挿で、1,000,000個のコンマ区切り整数の2,500個の文字列を処理するのに2分強かかります。

N <- 1000000
x <- sample(0:1, N, replace = TRUE)
s <- paste(x, collapse = ",")

# this is a vector of 10 strings
M <- 10
S <- rep(s, M)

system.time(y <- strsplit(S, split = ","))
# user  system elapsed 
# 6.57    0.00    6.56 
system.time(y <- strsplit(S, split = ",", fixed = TRUE))
# user  system elapsed 
# 0.46    0.03    0.50

これは、スキャンを使用するよりもほぼ3倍高速です。

system.time(scan(textConnection(S), sep=",", what="a"))
# Read 10000000 items
# user  system elapsed 
# 1.21    0.09    1.42
于 2012-08-21T01:39:16.467 に答える
2

迅速な修正の1つは、forループ内のペーストを削除することです。

subchar3<-function(inputstring, pos){
string = ""
memory = 0
for(num in pos){
    string = c(string,substr(inputstring, (memory+1), (num-1)))
    memory = num
}
string = paste(c(string, substr(inputstring,(memory+1), nchar(inputstring))),collapse = "")
return(string)
}
data<-paste(sample(letters,100000,replace=T),collapse='')
remove<-sample(1:nchar(data),200)
remove<-remove[order(remove)]
s2<-subchar2(data,remove)
s3<-subchar3(data,remove)
identical(s2,s3)
#[1] TRUE

> library(rbenchmark)
> benchmark(subchar2(data,remove),subchar3(data,remove),replications=10)
                    test replications elapsed relative user.self sys.self
1 subchar2(data, remove)           10   43.64 40.78505     39.97      1.9
2 subchar3(data, remove)           10    1.07  1.00000      1.01      0.0
  user.child sys.child
1         NA        NA
2         NA        NA
于 2012-08-21T01:15:06.823 に答える