使用动态前置零点调整数据集中的因子

时间:2012-04-24 14:45:12

标签: r r-factor

我有一个很大的data.frame(1.9M记录,有20列)。其中一列是因子列,其值为不同长度的数字(不同的字符/数字,例如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

我尝试了不同的方法,但现在我被卡住了。问题在于整个数据集中因子的长度不同。

我尝试了以下示例。

使用我执行代码的三个不同列创建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'代码,它会为我提供所有记录长度的向量,因此我认为它应该有效...

> 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

为什么nchar(as.character(levels(df.test$V1)))不能作为向量运算符运行? 谁能告诉我如何更改我的代码,那么它会得到正确的结果吗?

提前致谢!

NB。请注意,在实际情况下,我只需要在data.frame的一列上执行此调整。

3 个答案:

答案 0 :(得分: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])

也许有更好的方法......但您可以gsub使用sprintf

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

答案 1 :(得分: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

答案 2 :(得分: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 = '')
}