2012-04-24 51 views
0

我有一個大的data.frame(1.9M記錄,20列)。其中一列是具有不同長度數字值的因子列(不同數量的字符/數字,例如567839,2344324324,3243211等)。 注意:這些是數字代碼,沒有實際值,也可能只是字符這個例子的長度不同。使用動態前置零點調整數據集中的因子

現在我想轉換並因素成爲13位因素,以這樣的方式,一個因素得到前面的零的情況下的位數少於13

例子:

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

我嘗試了不同的方法,但現在我卡住了。問題在於整個數據集中因素的長短不一。

我嘗試了下面的例子。

創建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但只有一個值的長度;該因子的第一級別的長度(字母/升序)。它在所有記錄上執行必要的前面的零的數量。所以沒有矢量代碼!

注:如果我運行「的nchar」代碼seperately它給我的所有記錄,結果長度的矢量,所以我認爲它應該工作...

> 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)))作爲矢量運算符運行? 任何人都可以告訴我如何更改我的代碼,所以它會有正確的結果嗎?

在此先感謝!

注意:請注意,在實際情況下,我只需要對data.frame的一列執行此調整。

回答

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 2012-04-24 15:07:16

+0

@joran這是一個好點,當然值得考慮。然而,''%s'「填充」空格而不是零。對於該方法,您可以使用底部示例,因爲級別的因素被視爲字符串。然後'gsub'把空格改爲''0'。 – Justin 2012-04-24 15:10:16

+1

你確定嗎? 'sprintf('%05s',as.character(1:5))'填充0對我來說就好了。 – joran 2012-04-24 15:13:10

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 2012-04-24 15:50:12

+0

是的。 2.14.2。我還在OSX 10.5.8上。 – 2012-04-24 15:52:19

+0

這種方法不適用於我...只有空白,沒有零。可能與版本有關?我在Windows 7上運行2.14.2順便說一句, – FBE 2012-04-24 18:05:26

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 = '') 
}