5

文字列を一定間隔で分割したいと思います。私の質問はこれとほぼ同じです:文字列を特定の長さの部分文字列に分割する方法は? ただし、データセットには 1 つの文字列ではなく、文字列の列があります。

データセットの例を次に示します。

df = read.table(text = "
my.id   X1    
010101   1
010102   1
010103   1
010104   1
020101   1
020112   1
021701   0
021802   0
133301   0
133302   0  
241114   0
241215   0
", header = TRUE, colClasses=c('character', 'numeric'), stringsAsFactors = FALSE)

これが望ましい結果です。次のように、先頭のゼロを削除したいと思います。

desired.result = read.table(text = "
A1 A2 A3   X1
 1  1  1   1
 1  1  2   1
 1  1  3   1
 1  1  4   1
 2  1  1   1
 2  1 12   1
 2 17  1   0
 2 18  2   0
13 33  1   0
13 33  2   0
24 11 14   0
24 12 15   0
", header = TRUE, colClasses=c('numeric', 'numeric', 'numeric', 'numeric'), stringsAsFactors = FALSE)

ここに近いと思われるループがあり、おそらくそれを使用できます。ただし、もっと効率的な方法がある可能性が高いと考えています。

for(i in 1:nrow(df)) {
     print(substring(df$my.id[i], seq(1, 5, 2), seq(2, 6, 2)))
}

このapplyステートメントは機能しません。

apply(df$my.id, 1,  function(x) substring(df$my.id[x], seq(1, 5, 2), seq(2, 6, 2))   )

ご提案ありがとうございます。ベースRでのソリューションを好みます。

4

4 に答える 4

10

これにアプローチできるさまざまな方法の中で、 a にread.fwf適用されるtextConnection方法が最も効率的で理解しやすいことがわかりました。read.* 関数に組み込まれている自動クラス検出の利点があります。

cbind( read.fwf(file=textConnection(df$my.id), 
              widths=c(2,2,2), col.names=paste0("A", 1:3)), 
     X1=df$X1)
#-----------
   A1 A2 A3 X1
1   1  1  1  1
2   1  1  2  1
3   1  1  3  1
4   1  1  4  1
5   2  1  1  1
6   2  1 12  1
7   2 17  1  0
8   2 18  2  0
9  13 33  1  0
10 13 33  2  0
11 24 11 14  0
12 24 12 15  0

(これは約 6 年前に Rhelp で Gabor Grothendieck から学んだことだと思います。)

正規表現戦略を好む場合は、これを見てください。これは、2 つの位置ごとにタブを挿入し、read.table を介して実行します。非常にコンパクト:

read.table(text=gsub('(.{2})','\\1\t',df$my.id) )
#---------
   V1 V2 V3
1   1  1  1
2   1  1  2
3   1  1  3
4   1  1  4
5   2  1  1
6   2  1 12
7   2 17  1
8   2 18  2
9  13 33  1
10 13 33  2
11 24 11 14
12 24 12 15
于 2013-02-19T01:14:00.363 に答える
3

あなたはほとんどそこにいます。またはに変更applyし、動作するものを変更します。sapplyvapplysubstring

splt <- sapply(df$my.id, function(x) substring(x, seq(1, 5, 2), seq(2, 6, 2))   )
#this will produce the same thing
splt <- vapply(df$my.id, function(x) substring(x, seq(1, 5, 2), seq(2, 6, 2)),c("","","")   )
#     010101 010102 010103 010104 020101 020112 021701 021802 133301 133302 241114 241215
#[1,] "01"   "01"   "01"   "01"   "02"   "02"   "02"   "02"   "13"   "13"   "24"   "24"  
#[2,] "01"   "01"   "01"   "01"   "01"   "01"   "17"   "18"   "33"   "33"   "11"   "12"  
#[3,] "01"   "02"   "03"   "04"   "01"   "12"   "01"   "02"   "01"   "02"   "14"   "15"

これらを数値にしたかったのです。行列は、データ フレームで動作するように転置する必要もあります。両方の手順を次のように実行できます。

splt <- apply(splt,1,as.numeric)
    # [,1] [,2] [,3]
 # [1,]    1    1    1
 # [2,]    1    1    2
 # [3,]    1    1    3
 # [4,]    1    1    4
 # [5,]    2    1    1
 # [6,]    2    1   12
 # [7,]    2   17    1
 # [8,]    2   18    2
 # [9,]   13   33    1
# [10,]   13   33    2
# [11,]   24   11   14
# [12,]   24   12   15

これを古いデータ フレームと一緒に戻す必要があります。以下のようなものが考えられます。

df <- cbind(splt,df)
#    1  2  3  my.id X1
#1   1  1  1 010101  1
#2   1  1  2 010102  1
#3   1  1  3 010103  1
#4   1  1  4 010104  1
#5   2  1  1 020101  1
#6   2  1 12 020112  1
#7   2 17  1 021701  0
#8   2 18  2 021802  0
#9  13 33  1 133301  0
#10 13 33  2 133302  0
#11 24 11 14 241114  0
#12 24 12 15 241215  0

などで、必要に応じて列名を変更できますnames(df)[1:3] <- c("A1","A2","A3")

于 2013-02-19T01:00:07.873 に答える
2

gsub といくつかの正規表現を使用します。私はこのようなことをします(あまりエレガントではありませんが、仕事はします)

cbind(
as.numeric(gsub('([0-9]{2})([0-9]{2})([0-9]{2})','\\1',df$my.id)),
as.numeric(gsub('([0-9]{2})([0-9]{2})([0-9]{2})','\\2',df$my.id)),
as.numeric(gsub('([0-9]{2})([0-9]{2})([0-9]{2})','\\3',df$my.id)),
df$X1)

    [,1] [,2] [,3] [,4]
 [1,]    1    1    1    1
 [2,]    1    1    2    1
 [3,]    1    1    3    1
 [4,]    1    1    4    1
 [5,]    2    1    1    1
 [6,]    2    1   12    1
 [7,]    2   17    1    0
 [8,]    2   18    2    0
 [9,]   13   33    1    0
[10,]   13   33    2    0
[11,]   24   11   14    0
[12,]   24   12   15    0

編集

あまりエレガントではないと言ったので、 @mnel 命題を追加します。

x <- gsub('([0-9]{2})([0-9]{2})([0-9]{2})','\\1-\\2-\\3',df$my.id)
do.call(rbind, lapply(strsplit(x,'-'), as.numeric)) 
于 2013-02-19T01:01:44.140 に答える
2

regexを使用して、各 2 桁のセクションを抽出することもできます。

str_extract_allこれをfromと組み合わせて使用​​しましたstringr

do.call(rbind,lapply(str_extract_all(as.character(df[['my.id']]), pattern = '[[:digit:]]{2}'), as.numeric))
于 2013-02-19T01:05:44.860 に答える