我想以下列方式生成随机字符串:ABCDE1234E
,即每个字符串包含5个字符,4个数字,然后是1个字符。
我想出了一种使用以下代码创建它的方法。
library(random)
string_5 <- as.vector(randomStrings(n=5000, len=5, digits=FALSE, upperalpha=TRUE,
loweralpha=FALSE, unique=TRUE, check=TRUE))
number_4 <- as.vector(randomNumbers(n=5000, min=1111, max=9999, col=5, base=10, check=TRUE))
string_1 <- as.vector(randomStrings(n=5000, len=1, digits=FALSE, upperalpha=TRUE,
loweralpha=FALSE, unique=FALSE, check=TRUE))
PAN.Number <- paste(string_5,number_4,string_1,sep = "")
但是这些功能需要很长时间,random
库需要网络连接。
> system.time(string_5 <- as.vector(randomStrings(n=5000, len=5, digits=FALSE, upperalpha=TRUE,
+ loweralpha=FALSE, unique=TRUE, check=TRUE)))
user system elapsed
0.07 0.00 3.18
有什么方法可以尝试减少执行时间吗?
我也尝试使用sample()
,但我无法弄清楚。
答案 0 :(得分:24)
使用&#34; stringi&#34;正如@akrun所建议的那样会更快,但以下也非常快,不需要任何额外的包:
myFun <- function(n = 5000) {
a <- do.call(paste0, replicate(5, sample(LETTERS, n, TRUE), FALSE))
paste0(a, sprintf("%04d", sample(9999, n, TRUE)), sample(LETTERS, n, TRUE))
}
示例输出:
myFun(10)
## [1] "BZHOF3737P" "EPOWI0674X" "YYWEB2825M" "HQIXJ5187K" "IYIMB2578R"
## [6] "YSGBG6609I" "OBLBL6409Q" "PUMAL5632D" "ABRAT4481L" "FNVEN7870Q"
答案 1 :(得分:18)
我们可以使用stri_rand_strings
stringi
library(stringi)
sprintf("%s%s%s", stri_rand_strings(5, 5, '[A-Z]'),
stri_rand_strings(5, 4, '[0-9]'), stri_rand_strings(5, 1, '[A-Z]'))
或更紧凑
do.call(paste0, Map(stri_rand_strings, n=5, length=c(5, 4, 1),
pattern = c('[A-Z]', '[0-9]', '[A-Z]')))
system.time({
do.call(paste0, Map(stri_rand_strings, n=5000, length=c(5, 4, 1),
pattern = c('[A-Z]', '[0-9]', '[A-Z]')))
})
# user system elapsed
# 0 0 0
使用OP方法即使对于预期输出的一部分也可以重现时间
system.time(string_5 <- as.vector(randomStrings(n=5000, len=5, digits=FALSE, upperalpha=TRUE,
loweralpha=FALSE, unique=TRUE, check=TRUE)))
# user system elapsed
# 0.86 0.24 5.52
答案 2 :(得分:5)
您可以直接执行您想要的操作: 样本随机5个大写字母 样本4位数 样本1随机大写字母
digits = 0:9
createRandString<- function() {
v = c(sample(LETTERS, 5, replace = TRUE),
sample(digits, 4, replace = TRUE),
sample(LETTERS, 1, replace = TRUE))
return(paste0(v,collapse = ""))
}
这将更容易控制,并且不会花费很长时间。
答案 3 :(得分:2)
您的性能问题来自于首先使用random
软件包:您可以在互联网搜索中找到random::randomStrings()
功能,并认为它很好生成随机字符串以在程序中使用的方法,但random
包不适用于通用编程。它的工作原理是查询RANDOM.ORG服务器,它本质上比R的内置伪随机数生成器慢。
来自vignettes from the random package之一:
在许多情况下,希望使用非确定性确定 随机数。例子包括
- 使用真正独立的种子在不同节点上播种分布式计算;
- 获取不依赖于特定操作系统的RNG的可移植初始化 或硬件功能;
- 使用非确定性随机数验证模拟结果;
- 提供用于彩票图画或游戏的不确定种子......
请注意,大多数这些示例都是关于种子或初始化(这些是同义词)R的内置伪随机数生成器,而非替换他们......
答案 4 :(得分:1)
我们现在可以使用 dplyr 中的“rowwise”和“mutate”来做到这一点,stri_rand_strings 函数使用 library(stringi):
df %>%
rowwise() %>%
mutate(unique_id = paste0(stri_rand_strings(1, 5, "[A-Z]"), stri_rand_strings(1, 4, "[0-9]"), stri_rand_strings(1, 1, "[A-Z]")))
这避免了创建函数的需要。
答案 5 :(得分:0)
万一有人来这里寻找生成随机文件名的方法,这就是我使用的方法。我喜欢它的优雅
library(dplyr)
runif(1, 1000000000000, 9999999999999) %>% round %>% as.character %>% paste0("/tmp/", ., ".png")
注意:您可以通过将1
中的runif()
更改为所需的数字来轻松更改它生成的随机字符串
答案 6 :(得分:0)
您可以使用ASCII表来更好地控制最终字符串。
randString <- function(characters=0, numbers=0, symbols=0, lowerCase=0, upperCase=0) {
ASCII <- NULL
if(symbols>0) ASCII <- c(ASCII, sample(c(33:47, 58:34, 91:96, 123:126), symbols))
if(numbers>0) ASCII <- c(ASCII, sample(48:57, numbers))
if(upperCase>0) ASCII <- c(ASCII, sample(65:90, upperCase))
if(lowerCase>0) ASCII <- c(ASCII, sample(97:122, lowerCase))
if(characters>0) ASCII <- c(ASCII, sample(c(65:90, 97:122), characters))
return( rawToChar(as.raw(sample(ASCII, length(ASCII)))) )
}
示例:
randString(characters=5, numbers=4)
# [1] "9fKW75o1N"