我有一组看起来像这样的数据:
anim <- c(25499,25500,25501,25502,25503,25504)
sex <- c(1,2,2,1,2,1)
wt <- c(0.8,1.2,1.0,2.0,1.8,1.4)
data <- data.frame(anim,sex,wt)
data
anim sex wt anim2
1 25499 1 0.8 2
2 25500 2 1.2 2
3 25501 2 1.0 2
4 25502 1 2.0 2
5 25503 2 1.8 2
6 25504 1 1.4 2
我希望在每个动物ID之前添加零:
data
anim sex wt anim2
1 025499 1 0.8 2
2 025500 2 1.2 2
3 025501 2 1.0 2
4 025502 1 2.0 2
5 025503 2 1.8 2
6 025504 1 1.4 2
为了感兴趣,如果我需要在动物ID之前添加两个或三个零,该怎么办?
答案 0 :(得分:471)
版本较长:
有多种功能可用于格式化数字,包括添加前导零。哪一个最好取决于你想要做的其他格式。
问题的例子非常简单,因为所有的值都有相同的数字位数,所以让我们尝试一个更难的例子来制作10宽度8的幂。
anim <- 25499:25504
x <- 10 ^ (0:5)
paste
(它的变体paste0
)通常是您遇到的第一个字符串操作函数。它们并非真正用于操纵数字,但它们可用于此。在我们总是必须预先设置一个零的简单情况下,paste0
是最好的解决方案。
paste0("0", anim)
## [1] "025499" "025500" "025501" "025502" "025503" "025504"
对于数字中有可变位数的情况,你必须手动计算要预先设置的零数,这是非常可怕的,你应该只是出于病态的好奇心。
stringr
的 str_pad
与paste
的工作方式类似,因此您可以更明确地表达内容。
library(stringr)
str_pad(anim, 6, pad = "0")
## [1] "025499" "025500" "025501" "025502" "025503" "025504"
同样,它并不是真的设计用于数字,所以更难的情况需要一点思考。我们应该只能说“用零填充宽度为8”,但看看这个输出:
str_pad(x, 8, pad = "0")
## [1] "00000001" "00000010" "00000100" "00001000" "00010000" "0001e+05"
您需要设置科学惩罚option,以便始终使用固定符号(而不是科学符号)格式化数字。
library(withr)
with_options(
c(scipen = 999),
str_pad(x, 8, pad = "0")
)
## [1] "00000001" "00000010" "00000100" "00001000" "00010000" "00100000"
stringi
中的 stri_pad
与str_pad
中的stringr
完全相同。
formatC
是C函数printf
的接口。使用它需要了解该底层函数的arcana(参见链接)。在这种情况下,重点是width
参数,format
为"d"
为“整数”,而"0"
flag
为前置零。
formatC(anim, width = 6, format = "d", flag = "0")
## [1] "025499" "025500" "025501" "025502" "025503" "025504"
formatC(x, width = 8, format = "d", flag = "0")
## [1] "00000001" "00000010" "00000100" "00001000" "00010000" "00100000"
这是我最喜欢的解决方案,因为它很容易修改宽度,而且功能强大到足以进行其他格式更改。
sprintf
是同名C函数的接口;比如formatC
,但语法不同。
sprintf("%06d", anim)
## [1] "025499" "025500" "025501" "025502" "025503" "025504"
sprintf("%08d", x)
## [1] "00000001" "00000010" "00000100" "00001000" "00010000" "00100000"
sprintf
的主要优点是您可以在较长的文本位中嵌入格式化的数字。
sprintf(
"Animal ID %06d was a %s.",
anim,
sample(c("lion", "tiger"), length(anim), replace = TRUE)
)
## [1] "Animal ID 025499 was a tiger." "Animal ID 025500 was a tiger."
## [3] "Animal ID 025501 was a lion." "Animal ID 025502 was a tiger."
## [5] "Animal ID 025503 was a tiger." "Animal ID 025504 was a lion."
为了完整性,值得一提的是偶尔有用的其他格式化函数,但没有预先添加零的方法。
format
,一种用于格式化任何类型对象的通用函数,带有数字方法。它有点像formatC
,但还有另一个界面。
prettyNum
是另一种格式化功能,主要用于创建手动轴刻度标签。它适用于各种数字。
scales
包具有多种功能,例如percent
,date_format
和dollar
,适用于专业格式类型。
答案 1 :(得分:198)
对于无论data$anim
中有多少位数都能正常工作的一般解决方案,请使用sprintf
功能。它的工作原理如下:
sprintf("%04d", 1)
# [1] "0001"
sprintf("%04d", 104)
# [1] "0104"
sprintf("%010d", 104)
# [1] "0000000104"
在您的情况下,您可能需要:data$anim <- sprintf("%06d", data$anim)
答案 2 :(得分:28)
扩展@ goodside&#39; s repsonse:
在某些情况下,您可能希望用零填充字符串(例如fips代码或其他类似数字的因子)。在OSX / Linux中:
> sprintf("%05s", "104")
[1] "00104"
但是因为sprintf()
调用操作系统的C sprintf()
命令,讨论here,在Windows 7中会得到不同的结果:
> sprintf("%05s", "104")
[1] " 104"
因此,在Windows机器上,解决方法是:
> sprintf("%05d", as.numeric("104"))
[1] "00104"
答案 3 :(得分:20)
str_pad
是另一种选择。
stringr
答案 4 :(得分:2)
data$anim <- sapply(0, paste0,data$anim)
答案 5 :(得分:2)
这是一个通用的基本R函数:
const getData = () => Promise.all([$.getJSON("getData.php"), $.getJSON("getOtherData.php")]);
getData()
.then(([data1, data2]) => { // note that data1, data2 are now the arguments to the function
let markerlist = [];
for (let i = 0; i< data1.length; i++) {
...
...
}
})
.catch(err => {
// handle errors here
});
我喜欢pad_left <- function(x, len = 1 + max(nchar(x)), char = '0'){
unlist(lapply(x, function(x) {
paste0(
paste(rep(char, len - nchar(x)), collapse = ''),
x
)
}))
}
pad_left(1:100)
,但附带以下警告:
但是实际实施将遵循C99标准,并且详细信息(尤其是在用户错误下的行为)可能取决于平台
答案 6 :(得分:1)
这是将{0}添加到字符串的另一种选择,有时候看起来像一个数字,许多应用程序(如Excel)会损坏并删除前导0或将它们转换为科学记数法。
当我尝试@metasequoia提供的答案时,返回的向量具有前导空格而不是0
s。这与@ user1816679提到的问题相同 - 删除0
周围的引号或从%d
更改为%s
也没有任何区别。仅供参考,我正在使用在Ubuntu服务器上运行的RStudio Server。这个小小的两步解决方案对我有用:
gsub(pattern = " ", replacement = "0", x = sprintf(fmt = "%09s", ids[,CUSIP]))
使用%>%
包中的magrittr
管道函数,它看起来像这样:
sprintf(fmt = "%09s", ids[,CUSIP]) %>% gsub(pattern = " ", replacement = "0", x = .)
我更喜欢单功能解决方案,但它有效。
答案 7 :(得分:0)
对于您希望数字字符串保持一致的其他情况,我创建了一个函数。
有人可能觉得这很有用:
idnamer<-function(x,y){#Alphabetical designation and number of integers required
id<-c(1:y)
for (i in 1:length(id)){
if(nchar(id[i])<2){
id[i]<-paste("0",id[i],sep="")
}
}
id<-paste(x,id,sep="")
return(id)
}
idnamer("EF",28)
抱歉格式化。