R:如何计算调查回复中可能(人为)四舍五入的实例

问题描述 投票:0回答:1

我有一个较大的人口普查/BLS 数据集,其中包含大约 1000 万人的记录,每条记录大约有 250 个变量,包括缺失值。其中许多价值都是美元金额。我怀疑,但不知道,最右边的数字不成比例地是零。我想计算从右边开始的连续零的数量,并排除小数点后的任何内容。我想生成一个表,显示不同数量的零出现的频率,另一个表显示不同数字作为最右边的非零数字出现的频率。

如果我的数字是

13,568,700
   449,000
    43,560
    20,010
    34,600
    32,620

我想要的桌子是 对于零:

 3.   1
 2.   2
 1.   3

对于最右边的非零数字:

digit.      count
      1.    1
      2.    1
      6.    2
      7.    1
      9.    1

我有一个函数可以对单个数字执行此操作并适当增加一些计数器,但它根本不是矢量化的,而且速度慢得令人无法接受。因为有很多变量可能会针对每个人进行四舍五入,所以如果我只对每个数字运行该函数一次,我需要运行大约 500,000,000 次。如果我想要最左边的数字,则很容易矢量化,但我无法为右侧零的数量或最右侧非零数字制定矢量化算法。

如果有人比我更聪明,或者至少比我更有知识,我会很感激。

r performance rounding exploratory-data-analysis
1个回答
0
投票

从概念证明等不太快的事情开始:

n = 5E7
set.seed(42)
library(tidyverse)
df1 <- tibble(signif = rpois(n, lambda = 2),
              x = floor(runif(n, max = 1000)) * 10^signif)
# Here I'll start with 50M rows
# (note, my fake data is a little misleading because it will understate some
# significant digits, e.g. when runif produces a number ending with zeroes.


tictoc::tic()
df2 <- df1 |>
  mutate(v1 = format(x, trim = TRUE, scientific = FALSE),
         zeroes = nchar(x) - nchar(sub("0*$", "", format(x, trim = TRUE, scientific = FALSE))),
         right_dig = (x %/% (10^zeroes)) %% 10)
tictoc::toc()

这在我的机器上大约需要 90 秒,而你需要 10 倍的时间和多个列,因此还有很大的改进空间,但在紧要关头也许可以达到临界值。

结果

# A tibble: 50,000,000 × 5
   signif       x v1      zeroes right_dig
    <int>   <dbl> <chr>    <int>     <dbl>
 1      4 9020000 9020000      4         2
 2      4 3770000 3770000      4         7
 3      1    5370 5370         1         7
 4      3  540000 540000       4         4
 5      2   95900 95900        2         9
 6      2   33700 33700        2         7
 7      3  656000 656000       3         6
 8      0     152 152          0         2
 9      2   43100 43100        2         1
10      3  659000 659000       3         9
# ℹ 49,999,990 more rows
# ℹ Use `print(n = ...)` to see more rows

然后就可以直接快速地运行这些:

df2 %>% 
  count(zeroes)

# A tibble: 6 × 2
  zeroes        n
   <int>    <int>
1      0  6094178
2      1 12837105
3      2 13457359
4      3  9459420
5      4  5228366
6      5  2923572


df2 %>% 
  count(right_dig)

# A tibble: 10 × 2
   right_dig       n
       <dbl>   <int>
 1         0 1234711
 2         1 5419854
 3         2 5419492
 4         3 5418213
 5         4 5417654
 6         5 5414904
 7         6 5418602
 8         7 5417624
 9         8 5419975
10         9 5418971
© www.soinside.com 2019 - 2024. All rights reserved.