Return 在 Python 中分箱后范围的下限或上限
Return the lowr or upper bound of a range after binning in Python
我使用 pd.cut 将以下 df 转换为 bins:
import numpy as np
import pandas as pd
df = pd.DataFrame(np.random.randint(0,100,size=(5, 4)), columns=list('ABCD'))
print(df)
newDF = pd.cut(df.A, 2, precision=0)
print(newDF)
A B C D
0 83 43 99 85
1 6 57 44 45
2 5 72 10 53
3 24 50 23 18
4 75 25 96 27
0 (44.0, 83.0]
1 (5.0, 44.0]
2 (5.0, 44.0]
3 (5.0, 44.0]
4 (44.0, 83.0]
有没有办法return范围的下限或上限而不是整个范围?例如从上面的例子:
0 44.0
1 5.0
2 5.0
3 5.0
4 44.0
使用Series.map
:
pd.cut(df.A, 2, precision=0).map(lambda x: x.left)
s = pd.cut(df.A, 2, precision=0)
pd.Series(data=pd.IntervalIndex(s).left, index = s.index)
#print(df)
#
#
# A B C D
#0 26 70 28 2
#1 49 42 56 28
#2 48 26 40 19
#3 3 50 17 3
#4 20 34 54 42
#
#
#pd.cut(df.A, 2, precision=0).map(lambda x: x.left)
#
#0 3.0
#1 26.0
#2 26.0
#3 3.0
#4 3.0
#Name: A, dtype: category
#Categories (2, float64): [3.0 < 26.0]
对于数值,如果您将常量传递给 bins
,pd.cut
将只针对 np.linspace(min,max, bins+1)
进行剪切。所以
bins = 2
interval_bins = np.linspace(df.A.min(), df.A.max(),bins+1)
lefts = interval_bins[:-1]
rights = inteval_bins[1:]
这与@ansev 的回答差别不大。但是,我真的想要 pd.Series
对象的 IntervalDtype
访问器,这样这种事情就可以工作了。
# THIS IS NOT REAL!
# JUST AN EXAMPLE
# OF WHAT I WANT
newDF.astype(pd.IntervalDtype()).interval.left
所以,在寻找这样的东西时,我遇到了与@ansev 相同的东西。我希望这种情况将来会改变。我怀疑他们会添加一个 IntervalDtype
访问器(也许)。
我将提供一个简单的列表理解。这提供了一个简单的解决方案,无需创建额外的 pandas 个对象。
cats = newDF.cat.categories
codes = newDF.cat.codes
pd.Series([cats[code].left for code in codes], newDF.index)
0 54.0
1 54.0
2 14.0
3 14.0
4 54.0
dtype: float64
我使用 pd.cut 将以下 df 转换为 bins:
import numpy as np
import pandas as pd
df = pd.DataFrame(np.random.randint(0,100,size=(5, 4)), columns=list('ABCD'))
print(df)
newDF = pd.cut(df.A, 2, precision=0)
print(newDF)
A B C D
0 83 43 99 85
1 6 57 44 45
2 5 72 10 53
3 24 50 23 18
4 75 25 96 27
0 (44.0, 83.0]
1 (5.0, 44.0]
2 (5.0, 44.0]
3 (5.0, 44.0]
4 (44.0, 83.0]
有没有办法return范围的下限或上限而不是整个范围?例如从上面的例子:
0 44.0
1 5.0
2 5.0
3 5.0
4 44.0
使用Series.map
:
pd.cut(df.A, 2, precision=0).map(lambda x: x.left)
s = pd.cut(df.A, 2, precision=0)
pd.Series(data=pd.IntervalIndex(s).left, index = s.index)
#print(df)
#
#
# A B C D
#0 26 70 28 2
#1 49 42 56 28
#2 48 26 40 19
#3 3 50 17 3
#4 20 34 54 42
#
#
#pd.cut(df.A, 2, precision=0).map(lambda x: x.left)
#
#0 3.0
#1 26.0
#2 26.0
#3 3.0
#4 3.0
#Name: A, dtype: category
#Categories (2, float64): [3.0 < 26.0]
对于数值,如果您将常量传递给 bins
,pd.cut
将只针对 np.linspace(min,max, bins+1)
进行剪切。所以
bins = 2
interval_bins = np.linspace(df.A.min(), df.A.max(),bins+1)
lefts = interval_bins[:-1]
rights = inteval_bins[1:]
这与@ansev 的回答差别不大。但是,我真的想要 pd.Series
对象的 IntervalDtype
访问器,这样这种事情就可以工作了。
# THIS IS NOT REAL!
# JUST AN EXAMPLE
# OF WHAT I WANT
newDF.astype(pd.IntervalDtype()).interval.left
所以,在寻找这样的东西时,我遇到了与@ansev 相同的东西。我希望这种情况将来会改变。我怀疑他们会添加一个 IntervalDtype
访问器(也许)。
我将提供一个简单的列表理解。这提供了一个简单的解决方案,无需创建额外的 pandas 个对象。
cats = newDF.cat.categories
codes = newDF.cat.codes
pd.Series([cats[code].left for code in codes], newDF.index)
0 54.0
1 54.0
2 14.0
3 14.0
4 54.0
dtype: float64