有人可以解释一下Pandas bin的精度吗?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了有人可以解释一下Pandas bin的精度吗?相关的知识,希望对你有一定的参考价值。
所以我有大量的数据要分箱,看起来有点......慢?
我做了一个最小的例子,它模拟了较小子集的数据点和计算箱的数量:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import time
np.random.seed(1)
n_samples = 37000
n_bins = 91000
data = pd.Series(np.random.gamma(1, 1, n_samples))
t1 = time.time()
binned_df = pd.cut(data, bins = n_bins, precision = 100).value_counts()
t2 = time.time()
print("pd.cut speed: {}".format(t2-t1))
summed = np.sum(binned_df)
print("sum: {:.4f}".format(summed))
print("len: {}".format(len(binned_df)))
print(binned_df.head())
plt.hist(data, bins = 100)
plt.show()
如果我将pd.cut()
中的精度设置为100,那么我的计算机上的脚本大约需要1.5秒,而且我会得到非常精确的分档,例如(0.209274211931, 0.209375434515]
。但是,如果我将精度设置为1,则相同的动作大约需要9.2秒,因此速度要慢得多,现在这些动作仅被定义为例如(0.2093, 0.2094]
。
但为什么更高的精度计算得更快?我误解了这里发生了什么吗?
看看源代码,看起来给pandas
一个高于19的精度允许你跳过一个本来会运行的循环(如果你的dtype
不是datetime64
或timedelta64
;参见Line 326)。相关代码开始on Line 393 and goes to Line 415。双重评论是我的:
## This function figures out how far to round the bins after decimal place
def _round_frac(x, precision):
"""
Round the fractional part of the given number
"""
if not np.isfinite(x) or x == 0:
return x
else:
frac, whole = np.modf(x)
if whole == 0:
digits = -int(np.floor(np.log10(abs(frac)))) - 1 + precision
else:
digits = precision
return np.around(x, digits)
## This function loops through and makes the cuts more and more precise
## sequentially and only stops if either the number of unique levels created
## by the precision are equal to the number of bins or, if that doesn't
## work, just returns the precision you gave it.
## However, range(100, 20) cannot loop so you jump to the end
def _infer_precision(base_precision, bins):
"""Infer an appropriate precision for _round_frac
"""
for precision in range(base_precision, 20):
levels = [_round_frac(b, precision) for b in bins]
if algos.unique(levels).size == bins.size:
return precision
return base_precision # default
编辑:受控示例
假设你有一个列表my_list
,它有六个元素,你想分成三个箱子:
test = [1.121, 1.123, 1.131, 1.133, 1.141, 1.143]
很明显,你想要在1.123
和1.133
之后拆分,但是你说你没有直接给pandas
这些垃圾箱,而是垃圾箱的数量(n_bins = 3
)。假装pandas
开始猜测,切割将数据均匀分成3(注意:我不知道这是否是pandas
选择初始切割的方式 - 这只是为了示例目的):
# To calculate where the bin cuts start
x = (1.143 - 1.121)/3
cut1 = 1.121 + x # 1.1283
cut2 = 1.121 + (2*x) # 1.1356
bins = [cut1, cut2]
但除此之外,假设你建议pandas
使用精度为1.将此精度应用于上述切割会给你1.1
- 这对于分离my_list
是无用的,因为每个条目看起来像1.1
。所以包需要经过并在估计的切割值上使用越来越多的十进制数,直到得到的水平数与n_bins
相匹配:
# Adapted from infer_precision
for precision in range(1, 4):
levels = [_round_frac(b, precision) for b in bins]
print levels
此过程仅在唯一级别数与箱数匹配时停止,或者达到20个小数位。提供100的精度允许包在小数点后使用100个位置,以便在数据中的更多和更精确值之间剔除其切割值。
以上是关于有人可以解释一下Pandas bin的精度吗?的主要内容,如果未能解决你的问题,请参考以下文章