2012-04-24 5 views
0

私は大きいdata.frame(1.9Mレコード、20列)を持っています。列の1つは、長さの異なる数字の値を持つ因子列です(数字/数字の桁数が異なる、例えば567839,234324324,3243211など) 注:数値コードであり、実際の値ではなく、この例では異なる長さです。動的な先行ゼロのデータセットの要素を調整する

は今は要因が要因が先行取得するように13桁の因子、になることはない変換する桁数が13未満

例の場合にはゼロの:

Old factor  Length New factor 
432543532532 12  0432543532532 
3285087250932 13  3285087250932 
464577534  9  0000464577534 
2225324324324 13  2225324324324 
864235325264 12  0864235325264 

私はさまざまなアプローチを試みましたが、今は固まっています。問題は、要因の長さがデータセット全体で異なることです。

例を試してみましたが、

問題を特定するためにコードを実行する3つの異なる列を持つdata.frameを作成します。

> df.test <- as.data.frame(cbind(c("432543532532", "3285087250932", "464577534", "2225324324324", "864235325264"), c("3285087250932", "132543532532", "464577534", "2225324324324", "864235325264"), c("164577534", "3285087250932", "432543532532", "2225324324324", "864235325264"))) 
> df.test 
      V1   V2   V3 
1 432543532532 3285087250932  164577534 
2 3285087250932 132543532532 3285087250932 
3  464577534  464577534 432543532532 
4 2225324324324 2225324324324 2225324324324 
5 864235325264 864235325264 864235325264 

> levels(df.test$V1) <- paste(substr("0000000000000", 0, 13 - nchar(as.character(levels(df.test$V1)))), levels(df.test$V1), sep = '') 
> levels(df.test$V2) <- paste(substr("0000000000000", 0, 13 - nchar(as.character(levels(df.test$V2)))), levels(df.test$V2), sep = '') 
> levels(df.test$V3) <- paste(substr("0000000000000", 0, 13 - nchar(as.character(levels(df.test$V3)))), levels(df.test$V3), sep = '') 
> df.test 
      V1    V2    V3 
1 432543532532 03285087250932  0000164577534 
2 3285087250932 0132543532532 00003285087250932 
3  464577534  0464577534 0000432543532532 
4 2225324324324 02225324324324 00002225324324324 
5 864235325264 0864235325264 0000864235325264 

問題は、コードnchar(as.character(levels(df.test$V1)))ベクトルdf.test$V1ちょうど一つの値の長さを使用しないことです。係数の第1レベルの長さ(アルファベット/昇順)。そして、すべてのレコードに必要な先行ゼロの数を実行します。だからベクトルコードはありません!

注:私は別々に「NCHAR」のコードを実行し、それは私の結果として、すべてのレコードの長さのベクトルを与えるので、私は仮定した場合、それが動作するはずです...

> nchar(as.character(levels(df.test$V1))) 
[1] 13 13 12 9 12 
> nchar(as.character(levels(df.test$V2))) 
[1] 13 14 14 10 13 
> nchar(as.character(levels(df.test$V3))) 
[1] 13 17 17 16 16 

なぜISN」ベクターオペレータとして実行しているt nchar(as.character(levels(df.test$V1)))? 誰でも私のコードを変更する方法を教えてもらえますか?正しい結果が得られますか?

ありがとうございます!

NB。実際のケースでは、data.frameのonecolumnでこの調整を実行するだけでよいことに注意してください。

答えて

5

ゼロ埋め込みの場合はsprintf('%04d', 1:5)を使用できますが、例のコードは数値である必要があります。

max.nchar <- max(nchar(levels(df.test$V1))) 

sprintf(paste0('%0',max.nchar), as.numeric(levels(df$V1))[df$V1]) 

はたぶんもっと良い方法がある...しかし、あなたはgsubsprintfで使用することができます。

gsub(' ', '0', sprintf('%04s', levels(factor(10:15)))) 
+0

があなただけに 'のsprintf(「%の013s」、as.character(df.test $ V1を))'使用することはありませんがあることを確認する必要があり文字を直接ですか?その数字が多いと、整数や数値への変換の精度に問題が生じることがあります。 – joran

+0

@joran良い点と確かに検討する価値があると思います。しかし、 ''%s 'は "ゼロ"の代わりにスペースを "pad"します。その方法では、因子のレベルが文字列として扱われるので、下の例を使用することができます。スペースを '' 0 ''に '' gsub ''します。 – Justin

+1

本当ですか? 'sprintf( '%05s、as.character(1:5))'は私のために0のパッドを使っています。 – joran

1
as.data.frame(lapply(df.test, sprintf, fmt="%013s")) 
#---------------------  
     V1   V2   V3 
1 0432543532532 3285087250932 0000164577534 
2 3285087250932 0132543532532 3285087250932 
3 0000464577534 0000464577534 0432543532532 
4 2225324324324 2225324324324 2225324324324 
5 0864235325264 0864235325264 0864235325264 
+0

最後に!他の誰かが2.14.2を実行していますか?どのプラットフォーム? (私たちはちょうどRのチャットルームでこれについての会話を持っていた。) – joran

+0

うん。 2.14.2。私はまだOSX 10.5.8にいます。 –

+0

このメソッドは私のためには機能しませんでした...空白のみ、ゼロはありません。おそらくバージョンとは何か?私はWindows 7上で2.14.2 btwを実行しています。 – FBE

0

はあなたのコードが働いていなかったので、substrリターン「と同じ長さの文字ベクトルx(可能な強制後)と同じ属性を持ちます。だから、xがあなたの期待戻り値としてなど、多くの要素

df.test <- as.data.frame(cbind(c("432543532532", "3285087250932", "464577534", "2225324324324", "864235325264"), c("3285087250932", "132543532532", "464577534", "2225324324324", "864235325264"), c("164577534", "3285087250932", "432543532532", "2225324324324", "864235325264"))) 
df.test 

n <- nrow(df.test) 
start <- rep(0, n) 
padStrs <- rep("0000000000000", n) 
for (thevar in colnames(df.test))) { 
    cdiff1 <- 13 - nchar(as.character(levels(df.test[, thevar]))) 
    levels(df.test[, thevar]) <- paste(substr(padStrs, 0, cdiff), levels(df.test[, thevar]), sep = '') 
} 
関連する問題