R语言 返回带小数位的值中第一个小于5的数字的位置

5cg8jx4n  于 2022-12-05  发布在  其他
关注(0)|答案(4)|浏览(149)

我想知道小数点后第一个数字小于5的位置。如果不可能(所有数字都大于或等于5),则应返回数字的小数位数。
所以这个数据:

library(dplyr)
Data <- tibble(Number = c(0.998971282, 0.97871, 0.98121752874, 0.98921752874, 0.95171358,0.99999999))

应生成如下输出:

Data %>% mutate(Position = c(6, 5, 3, 4, 3, 8))
rsaldnfx

rsaldnfx1#

基本R

get_first_digit_below <- 
  function(x){
    str <- substr(x, 3, nchar(x))
    idx <- regexpr("[0-4]", str)
    idx[idx < 0] <- nchar(str)[idx < 0]
    as.vector(idx)
  }

get_first_digit_below(Data$Number)
#[1] 6 5 3 4 3 8

深度和字符串

library(stringr)
library(dplyr)
get_first_digit_below <- 
  function(x){
    str <- substr(x, 3, nchar(x))
    idx <- str_locate(str, "[0-4]")[, 1]
    coalesce(idx, str_length(str))
  }

get_first_digit_below(Data$Number)
#[1] 6 5 3 4 3 8
esyap4oy

esyap4oy2#

避免转换为字符的解决方案。

fFirstDigit <- function(v, x) {
  n <- -floor(log10(.Machine$double.eps))
  m <- matrix(as.integer((rep(v*10^(n - ceiling(log10(v))), each = n)/10^((n - 1L):0))%%10), length(v), n, TRUE)
  m[,n] <- 0L
  max.col(m < x, "f")
}

Number <- c(0.998971282, 0.97871, 0.98121752874, 0.98921752874, 0.95171358, 0.99999999, 1 - .Machine$double.eps, 987654321)
fFirstDigit(Number, 5L)
#> [1]  6  5  3  4  3  9 16  6
qzlgjiam

qzlgjiam3#

A基R方法使用strsplit

cbind(
  Data, Position = sapply(strsplit(as.character(Data$Number), ""), function(x){ 
    is <- as.numeric(x[3:length(x)]) < 5
    ifelse(any(is), which(is)[1], length(x[3:length(x)])) })
)
     Number Position
1 0.9989713        6
2 0.9787100        5
3 0.9812175        3
4 0.9892175        4
5 0.9517136        3
6 1.0000000        8

dplyr版本

library(dplyr)
library(stringr)

Data %>% 
  rowwise() %>% 
  mutate(n = str_split(Number, ""), 
         n = list(n[3:length(n)]), 
         Position = which(sapply(n, "<", 5))[1],
         Position = replace_na(Position, length(n)), n = NULL) %>%
  ungroup()
# A tibble: 6 × 2
  Number Position
   <dbl>    <int>
1  0.999        6
2  0.979        5
3  0.981        3
4  0.989        4
5  0.952        3
6  1.00         8
bjp0bcyl

bjp0bcyl4#

另一种方法是使用regexec。最后的和加上最后一个匹配的长度(零或一个[0-4]数字),以便如果存在这样的数字,则返回其位置,否则返回十进制数的个数。

c("0.998971282", "0.97871", "0.98121752874", 
  "0.98921752874", "0.95171358","0.99999999") |>
    regexec(pattern = "[0-9]+\\.([5-9]+)([0-4])?") |>
    sapply(FUN= attr, which = "match.length") |>
    (\(z) {z[2,] + z[3,]})()

[1] 6 5 3 4 3 8

相关问题