我将列表项排序到箱子时遇到问题。我有两个列表,X和Y,具有相应的X和Y值(显然也可以是一个元组列表)。接下来,我需要将X范围拆分为10个相等的区间,并将X值和相应的Y值排序到这些区域,这样我就知道Y值属于哪个X bin(即哪个bin落入每个Y的X值) ()),然后取每个bin中所有Y值的中位数。这给了我十个bin-median对。这在原理上工作正常,下面的代码我也计算每个bin的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))]
现在的问题是,有时bin是空的,因为此bin中没有X值。在这种情况下,行
bin_means = [np.median(np.asarray(Y)[digitized == j])
for j in range(1, len(bins))]
引发错误
/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/False
中尝试numpy.digitize
但没有运气。我认为最好在执行此列表计算之前删除三个列表bin_centers
,digitized
和bins
中的条目,以计算中值。但我不知道如何做到这一点,如何找出哪些垃圾箱是空的,然后从这些列表中删除什么以及如何删除。
有任何想法吗?谢谢!
答案 0 :(得分:1)
如果您有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)
产量
[ 15. 90. 50. 55. 40. 60.]
没有SciPy,我认为你需要列表理解。
正如您所建议的那样,您可以通过过滤掉那些空的垃圾箱来避免RuntimeWarning。你可以在列表理解中使用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')
有一种方法可以更快地计算bin_centers:
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]
如果你的目的只是制作散点图,那么就没有必要删除nans,因为matplotlib
无论如何都会忽略它们。
如果你真的想删除nans,那么你可以使用
no_nans = np.isfinite(bin_medians)
bin_medians = bin_medians[no_nans]
bin_centers = bin_centers[no_nans]
在上文中,我选择使用warnings.filterwarnings
来禁止警告。如果您不希望取消警告,并希望从bin_medians
和bin_centers
的相应位置过滤nans,则:
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()])
答案 1 :(得分:0)
我不太明白这个问题,但是有些事可能会让你开始:
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。
如果那不是你想要的,请道歉。