如何返回R中的小数位数
我在R工作。我有一系列以十进制度数表示的坐标,我想根据这些数字的小数位数对这些坐标进行排序(即,我想放弃小数位数太少的坐标)。如何返回R中的小数位数,r,R,我在R工作。我有一系列以十进制度数表示的坐标,我想根据这些数字的小数位数对这些坐标进行排序(即,我想放弃小数位数太少的坐标)。 R中是否有一个函数可以返回一个数字的小数位数,我可以将其合并到函数编写中? 输入示例: AniSom4 -17.23300000 -65.81700 AniSom5 -18.15000000 -63.86700 AniSom6 1.42444444 -75.86972 AniSom7
R中是否有一个函数可以返回一个数字的小数位数,我可以将其合并到函数编写中?
输入示例:
AniSom4 -17.23300000 -65.81700
AniSom5 -18.15000000 -63.86700
AniSom6 1.42444444 -75.86972
AniSom7 2.41700000 -76.81700
AniLac9 8.6000000 -71.15000
AniLac5 -0.4000000 -78.00000
理想情况下,我会编写一个脚本,丢弃AniLac9和Anilac5,因为这些坐标记录的精度不够。我想放弃经度和纬度都少于3个非零十进制值的坐标。在[R]中,2.30000和2.3之间没有差异,都被舍入到2.3,因此如果你想检查的话,一个比另一个精度不高。另一方面,如果这不是你的意思:如果你真的想这样做,你可以使用1)乘以10,2)使用floor()函数3)除以10 4)检查是否与原始值相等。(但是请注意,比较浮点值是否相等是一种不好的做法,请确保这是您真正想要的)您可以轻松地为任务编写一个小函数,例如:
decimalplaces <- function(x) {
if ((x %% 1) != 0) {
nchar(strsplit(sub('0+$', '', as.character(x)), ".", fixed=TRUE)[[1]][[2]])
} else {
return(0)
}
}
更新(2018年4月3日)以解决@owen88关于双精度浮点数舍入错误的报告——替换
x%%1
检查:
decimalplaces <- function(x) {
if (abs(x - round(x)) > .Machine$double.eps^0.5) {
nchar(strsplit(sub('0+$', '', as.character(x)), ".", fixed = TRUE)[[1]][[2]])
} else {
return(0)
}
}
decimalplaces.Machine$double.eps^0.5){
nchar(strsplit(sub('0+$,'',as.character(x)),”,fixed=TRUE)[[1]][[2]]
}否则{
返回(0)
}
}
这里有一种方法。它检查小数点后的前20位,但如果您有其他想法,可以调整数字20
x <- pi
match(TRUE, round(x, 1:20) == x)
根据罗曼的建议进行调整:
num.decimals <- function(x) {
stopifnot(class(x)=="numeric")
x <- sub("0+$","",x)
x <- sub("^.+[.]","",x)
nchar(x)
}
x <- "5.2300000"
num.decimals(x)
num.decimals对于普通应用程序,下面是对daroczig代码的修改,以处理向量:
decimalplaces <- function(x) {
y = x[!is.na(x)]
if (length(y) == 0) {
return(0)
}
if (any((y %% 1) != 0)) {
info = strsplit(sub('0+$', '', as.character(y)), ".", fixed=TRUE)
info = info[sapply(info, FUN=length) == 2]
dec = nchar(unlist(info))[seq(2, length(info), 2)]
return(max(dec, na.rm=T))
} else {
return(0)
}
}
我们现在有多少个小数?有趣的问题。这里是对上述受访者工作的另一个调整,矢量化,并扩展到处理小数点左侧的数字。针对负数进行测试,这将为以前的strsplit()
方法提供不正确的结果
如果希望只计算右侧的,则可以将trailingonly
参数设置为TRUE
nd1 <- function(xx,places=15,trailingonly=F) {
xx<-abs(xx);
if(length(xx)>1) {
fn<-sys.function();
return(sapply(xx,fn,places=places,trailingonly=trailingonly))};
if(xx %in% 0:9) return(!trailingonly+0);
mtch0<-round(xx,nds <- 0:places);
out <- nds[match(TRUE,mtch0==xx)];
if(trailingonly) return(out);
mtch1 <- floor(xx*10^-nds);
out + nds[match(TRUE,mtch1==0)]
}
字符串版本在15位处被截断(实际上,不确定为什么另一个的places参数被截断了1位…超出它的原因是它在两个方向上都计算数字,因此如果数字足够大,它的大小可能会增加一倍)。as.character()
可能有一些格式化选项,可以为nd2()
提供一个与nd1()的places
参数等价的选项
nd1()
更快
rowSums(replicate(10,system.time(replicate(100,nd1(c(1.1,-8.5,-5,145,5,10.15,pi,44532456.345243627,0))))));
rowSums(replicate(10,system.time(replicate(100,nd2(c(1.1,-8.5,-5,145,5,10.15,pi,44532456.345243627,0))))));
我不是想劫持线程,只是把它发布在这里,因为它可能会帮助某人处理我试图用建议的代码完成的任务
不幸的是,即使是@daroczig的解决方案,我也无法检查一个数字是否少于8位小数
@daroczig的代码:
decimalplaces <- function(x) {
if (abs(x - round(x)) > .Machine$double.eps^0.5) {
nchar(strsplit(sub('0+$', '', as.character(x)), ".", fixed = TRUE)[[1]][[2]])
} else {
return(0)
}
}
等等
到目前为止,我们能够使用以下笨拙的代码完成所需的测试:
if (abs(x*10^8 - floor(as.numeric(as.character(x*10^8)))) > .Machine$double.eps*10^8)
{
print("The number has more than 8 decimal digits")
}
PS:我可能遗漏了一些关于不取.Machine$double.eps
的根的内容,因此请小心另一个贡献,将其完全保留为数字表示,而不转换为字符:
countdecimals <- function(x)
{
n <- 0
while (!isTRUE(all.equal(floor(x),x)) & n <= 1e6) { x <- x*10; n <- n+1 }
return (n)
}
countdecimals基于daroczig函数的向量解决方案(也可以处理包含字符串和数字的脏列):
decimalplaces\u vec不确定为什么不使用上述简单方法(从tidyverse/magrittr加载管道)
因此R在内部似乎无法区分最初获得1.000
和1
。因此,如果一个人有一个各种十进制数的向量输入,通过取小数位数的最大值,可以看到它最初有(至少)多少个数字
编辑:修复了错误如果这里有人需要上面Gergely Daróczi提供的函数的矢量化版本:
decimalplaces <- function(x) {
ifelse(abs(x - round(x)) > .Machine$double.eps^0.5,
nchar(sub('^\\d+\\.', '', sub('0+$', '', as.character(x)))),
0)
}
decimalplaces(c(234.1, 3.7500, 1.345, 3e-15))
#> 1 2 3 0
decimalplaces.Machine$double.eps^0.5,
nchar(sub('^\\d+\\.','',sub('0+$','',as.character(x)),
0)
}
小数位数(c(234.1,3.7500,1.345,3e-15))
#> 1 2 3 0
我已经测试了一些解决方案,我发现这一解决方案对其他解决方案中报告的错误非常有效
countDecimalPlaces <- function(x) {
if ((x %% 1) != 0) {
strs <- strsplit(as.character(format(x, scientific = F)), "\\.")
n <- nchar(strs[[1]][2])
} else {
n <- 0
}
return(n)
}
# example to prove the function with some values
xs <- c(1000.0, 100.0, 10.0, 1.0, 0, 0.1, 0.01, 0.001, 0.0001)
sapply(xs, FUN = countDecimalPlaces)
countDecimalPlaces数据文件中的小数位数是如何记录的?例如,它可能同时有34.4和34.400,这些会被认为是不同的吗?示例输入和所需输出将很有帮助;小数位数在x86和其他主流处理器中无法准确表示。除了文本表示法,你会得到虚假的结果。或者将数据作为字符导入,计算“点”后面的字符数,并将其作为排序标准。我喜欢这个外观。非常感谢你的帮助!谢谢你@Pascal!我刚刚意识到我在函数中有一个输入错误(在as.character
函数中写了'num'而不是'x'),我已经纠正了这个错误。此外,我还添加了regexpr部分,因此数字/字符串末尾的零将自动删除。此函数非常有用,但是当给定一个数字(如63.0000)时,它会返回一个错误。有没有办法修改它,使其在这些情况下返回0?@schnee感谢您的反馈。或者,您可以将选项(scipen=999)
设置为不使用科学格式。as.character
不好——改用sprintf
<代码>as。字符
对于小/大“整数”数字(如1e6、1e-6)将失败。好主意!我想一定还有一个错误:decimalplaces2(c(1.2,2.34,3))
返回1-另外:传递少于3个数字会导致错误。我在序列中得到错误。默认值(2,长度(信息),2):wro
decimalplaces <- function(x) {
if (abs(x - round(x)) > .Machine$double.eps^0.5) {
nchar(strsplit(sub('0+$', '', as.character(x)), ".", fixed = TRUE)[[1]][[2]])
} else {
return(0)
}
}
NUMBER / NUMBER OF DECIMAL DIGITS AS PRODUCED BY THE CODE ABOVE
[1] "0.0000437 7"
[1] "0.000195 6"
[1] "0.00025 20"
[1] "0.000193 6"
[1] "0.000115 6"
[1] "0.00012501 8"
[1] "0.00012701 20"
if (abs(x*10^8 - floor(as.numeric(as.character(x*10^8)))) > .Machine$double.eps*10^8)
{
print("The number has more than 8 decimal digits")
}
countdecimals <- function(x)
{
n <- 0
while (!isTRUE(all.equal(floor(x),x)) & n <= 1e6) { x <- x*10; n <- n+1 }
return (n)
}
decimalplaces_vec <- function(x) {
vector <- c()
for (i in 1:length(x)){
if(!is.na(as.numeric(x[i]))){
if ((as.numeric(x[i]) %% 1) != 0) {
vector <- c(vector, nchar(strsplit(sub('0+$', '', as.character(x[i])), ".", fixed=TRUE)[[1]][[2]]))
}else{
vector <- c(vector, 0)
}
}else{
vector <- c(vector, NA)
}
}
return(max(vector))
}
count_decimals = function(x) {
#length zero input
if (length(x) == 0) return(numeric())
#count decimals
x_nchr = x %>% abs() %>% as.character() %>% nchar() %>% as.numeric()
x_int = floor(x) %>% abs() %>% nchar()
x_nchr = x_nchr - 1 - x_int
x_nchr[x_nchr < 0] = 0
x_nchr
}
> #tests
> c(1, 1.1, 1.12, 1.123, 1.1234, 1.1, 1.10, 1.100, 1.1000) %>% count_decimals()
[1] 0 1 2 3 4 1 1 1 1
> c(1.1, 12.1, 123.1, 1234.1, 1234.12, 1234.123, 1234.1234) %>% count_decimals()
[1] 1 1 1 1 2 3 4
> seq(0, 1000, by = 100) %>% count_decimals()
[1] 0 0 0 0 0 0 0 0 0 0 0
> c(100.1234, -100.1234) %>% count_decimals()
[1] 4 4
> c() %>% count_decimals()
numeric(0)
decimalplaces <- function(x) {
ifelse(abs(x - round(x)) > .Machine$double.eps^0.5,
nchar(sub('^\\d+\\.', '', sub('0+$', '', as.character(x)))),
0)
}
decimalplaces(c(234.1, 3.7500, 1.345, 3e-15))
#> 1 2 3 0
countDecimalPlaces <- function(x) {
if ((x %% 1) != 0) {
strs <- strsplit(as.character(format(x, scientific = F)), "\\.")
n <- nchar(strs[[1]][2])
} else {
n <- 0
}
return(n)
}
# example to prove the function with some values
xs <- c(1000.0, 100.0, 10.0, 1.0, 0, 0.1, 0.01, 0.001, 0.0001)
sapply(xs, FUN = countDecimalPlaces)