Binning python元组。空箱子导致的错误

2024-05-26 14:21:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个问题,排序清单项目到垃圾箱。我有两个列表,X和Y,以及相应的X和Y值(很明显,这也可能是一个元组列表)。接下来,我需要将X范围分成10个相等的箱子,并将X值和相应的Y值排序到这些箱子中,这样我就知道哪些Y值属于哪个X bin(即每个Y值的X值落入哪个bin中),然后取每个bin中所有Y值的中值。这给了我10个二进制中间值对。在下面的代码中,我还计算了每个箱子的X中心,这在原则上可以正常工作。在

    bins = np.linspace(max(X), min(X), 10)
    digitized = np.digitize(X, bins)
    bin_centers = []
    for j in range(len(bins) - 1):
        bin_centers.append((bins[j] + bins[j + 1]) / 2.)
    bin_means = [np.median(np.asarray(Y)[digitized == j])
                 for j in range(1, len(bins))]

现在的问题是,有时一个箱子是空的,因为这个箱子里没有X值。在这种情况下

^{pr2}$

引发错误

/usr/lib64/python2.6/site-packages/numpy/core/_methods.py:55: RuntimeWarning: Mean of empty slice.
FloatingPointError: invalid value encountered in double_scalars

因为空箱子。我该怎么解决呢?我也尝试了right=True/Falsenumpy.digitize中,但没有成功。我认为在进行计算中值的列表理解之前,最好删除三个列表bin_centersdigitized和{}中的条目。但我不知道如何做到这一点,如何找出哪些垃圾箱是空的,然后从这些清单中删除哪些内容以及如何删除。 有什么想法吗?谢谢!在


Tags: innumpy列表forlenbin排序np
2条回答

我不太明白这个问题,但这里有一些东西可以让你开始:

In [3]: X = [1,2,3,4,5,6,7,8,9,10]

In [4]: Y = [chr(96+x) for x in X]

In [8]: Z = zip(X, Y)    # Create a pairing - this can be done after a sort if they're not in whatever 'order' you want for your correspondence

In [9]: Z
Out[9]:
[(1, 'a'),
 (2, 'b'),
 (3, 'c'),
 (4, 'd'),
 (5, 'e'),
 (6, 'f'),
 (7, 'g'),
 (8, 'h'),
 (9, 'i'),
 (10, 'j')]

此时,您可以执行类似sorted(Z, key=lambda el: -ord(el[1]))之类的操作来根据您的条件进行排序。显然这比这个例子更有意义。在

最后,为了将块分成等长的部分,我想您可能也希望这样做,请看一下wide variety of possibilities given as answers here。在

如果那不是你想要的,道歉。在

如果您有Scipy,可以拨打scipy.stats.binned_statistic

import scipy.stats as stats
statistic, bin_edges, binnumber = stats.binned_statistic(
    x=X, values=Y, statistic='median', bins=bins)
statistic = statistic[np.isfinite(statistic)]
print(statistic)

收益率

^{pr2}$

如果没有SciPy,我想你需要一个列表理解。 正如您所建议的,您可以通过过滤掉那些空的容器来避免运行时警告。您可以使用列表理解中的if-condition来完成此操作:

masks = [(digitized == j) for j in range(1, len(bins))]
bin_medians = [np.median(Y[mask]) for mask in masks if mask.any()]

还请注意,您看到的错误消息是一个警告,而不是异常。您可以(或者)使用

import warnings
warnings.filterwarnings("ignore", 'Mean of empty slice.')
warnings.filterwarnings("ignore", 'invalid value encountered in double_scalar')

有一种快速计算u-bin的方法:

bin_centers = []
for j in range(len(bins) - 1):
    bin_centers.append((bins[j] + bins[j + 1]) / 2.)

可以简化为

bin_centers = bins[:-1] + (bins[1]-bins[0])/2

比如说

import numpy as np
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore", 'Mean of empty slice.')
warnings.filterwarnings("ignore", 'invalid value encountered in double_scalar')

np.random.seed(123)

X = np.random.random(10)
bins = np.linspace(min(X), max(X), 10)
digitized = np.digitize(X, bins)-1
bin_centers = bins + (bins[1]-bins[0])/2

Y = range(0, 100, 10)
Y = np.asarray(Y, dtype='float')
bin_medians = [np.median(Y[digitized == j]) for j in range(len(bins))]
print(bin_medians)

plt.scatter(bin_centers, bin_medians)
plt.show()

收益率

[15.0, 90.0, 50.0, 55.0, nan, 40.0, nan, nan, nan, 60.0]

enter image description here

如果您的目的只是绘制散点图,那么就不必删除nan,因为matplotlib无论如何都会忽略它们。在

如果你真的想移除nan,那么你可以使用

no_nans = np.isfinite(bin_medians)
bin_medians = bin_medians[no_nans]
bin_centers = bin_centers[no_nans]

在上面,我选择使用warnings.filterwarnings来抑制警告。如果您不希望抑制警告,而是希望从bin_medians和{}中过滤相应位置的nan,那么:

bin_centers = bins + (bins[1]-bins[0])/2
masks = [(digitized == j) for j in range(len(bins))]
bin_centers, bin_medians = zip(*[(center, np.median(Y[mask]))
                                 for center, mask in zip(bin_centers, masks)
                                 if mask.any()])

相关问题 更多 >

    热门问题