我有一个很大的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
的一列上执行此调整。
答案 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 = '')
}