我有以下熊猫DataFrame:

import numpy as np
import pandas as pd

np.random.seed(0)
test_df = pd.DataFrame({"category": ["A", "B"]*5, "value": np.random.uniform(size=10)})

print(test_df)
#  category     value
#0        A  0.548814
#1        B  0.715189
#2        A  0.602763
#3        B  0.544883
#4        A  0.423655
#5        B  0.645894
#6        A  0.437587
#7        B  0.891773
#8        A  0.963663
#9        B  0.383442


我想使用valuepandas.cut列进行装箱,但是bins参数需要根据category列而有所不同。

具体来说,我想使用以下字典来定义用于cut的容器:

bins = {
    "A": [0.00, 0.25, 0.50, 0.75, 1],
    #     0,    1,    2,    3,    4   <-- corresponding bin value
    "B": [0.00, 0.33, 0.66, 1]
    #     0,    1,    2,    3         <-- corresponding bin value
}


我想出了以下解决方案,该解决方案是首先使用所有垃圾箱削减value列:

cuts = {
    c: pd.cut(test_df["value"], bins=bins[c], labels=range(1, len(bins[c]))) for c in bins
}


然后使用numpy.select将适当的bin分配回test_df

test_df["bin"] = np.select(*zip(*[(test_df["category"] == c, cuts[c]) for c in bins]))
print(test_df)
#  category     value  bin
#0        A  0.548814    3
#1        B  0.715189    3
#2        A  0.602763    3
#3        B  0.544883    2
#4        A  0.423655    2
#5        B  0.645894    2
#6        A  0.437587    2
#7        B  0.891773    3
#8        A  0.963663    4
#9        B  0.383442    2


这是正确的答案,但是有没有更有效的方法?理想情况下,应该有一种方法不涉及在每个不同的容器上调用cut。在我的真实数据中,我有2个以上的箱。

最佳答案

也许将numpy与np.searchsorted一起使用:

test_df['bin'] = [np.searchsorted(bins[i], v) for i, v in test_df.values]


输出:

  category     value  bin
0        A  0.548814    3
1        B  0.715189    3
2        A  0.602763    3
3        B  0.544883    2
4        A  0.423655    2
5        B  0.645894    2
6        A  0.437587    2
7        B  0.891773    3
8        A  0.963663    4
9        B  0.383442    2


时机


  %timeit np.select(zip([(test_df [“ category”] == c,cuts [c])for c in
  垃圾箱])
  每个循环1.21 ms±14.3 µs(平均±标准偏差,共运行7次,每个循环1000个)





  %timeit [np.searchsorted(bins [i],v)for i,v in test_df.values]
  每个循环301 µs±4.14 µs(平均±标准偏差,共运行7次,每个循环1000个)

关于python - Pandas 通过基于另一列的bins参数有效地削减了列,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57314615/

10-11 08:55