Pandas:按范围对列值进行分类

7

I have a dataframe, df like this

a  b  c
1  0  2
5  7  8
4  1  3
3  4  6
5  2  5
.......

现在我想用以下范围替换这些数据。
0-3 = 1
4-6 = 2
7-9 = 3

列值小于10,因此范围在0-9之间。

我想用范围类别替换上述数据框中的值,并且输出应如下所示。

a  b  c
1  1  1
2  3  3
2  1  1
1  2  2
2  1  2
.......

如果数据框(df)中的任何值在0-3之间,则应替换为1,如果在4-6之间则替换为2,以此类推。

我该如何做到这一点?

3个回答

10
使用pd.cutapply结合使用,例如:
df.apply(lambda x : pd.cut(x,[-1,3,6,9],labels=[1,2,3]))
   a  b  c
0  1  1  1
1  2  3  3
2  2  1  1
3  1  2  2
4  2  1  2

一种非基于apply的解决方案,由@coldspeed提出:

pd.DataFrame(pd.cut(df.values.reshape(-1,),[-1,3,6,9],labels=[1,2,3]).codes.reshape(df.shape)+1,columns=df.columns)

或者
pd.DataFrame(pd.cut(np.hstack(df.values),[-1,3,6,9],labels=[1,2,3]).codes.reshape(df.shape)+1,columns=df.columns)

pd.cut是这样做的政治正确方式。 - cs95
哈哈,有时候你用的词真的很花哨。谢谢。 - Bharath M Shetty
1
摆脱 apply 函数。使用 pd.cut(df.values.reshape(-1, ),[-1,3,6,9],labels=[1,2,3]).codes.reshape(df.shape),然后将结果加载到数据框中。 - cs95
谢谢@cᴏʟᴅsᴘᴇᴇᴅ,我们需要在重塑后加上+1。 - Bharath M Shetty

4
使用一点数学魔法:
((df - 1) // 3).clip(0) + 1

   a  b  c
0  1  1  1
1  2  3  3
2  2  1  1
3  1  2  2
4  2  1  2

或者,用1替换所有零(唯一需要处理的特殊情况),然后进行除法运算。

(df.replace(0, 1) - 1) // 3 + 1

   a  b  c
0  1  1  1
1  2  3  3
2  2  1  1
3  1  2  2
4  2  1  2

1
不错的解决方案 ;) - jezrael

3
您可以使用 np.digitize 函数。
In [5942]: bins = np.array([0, 4, 7, 10])

In [5943]: pd.DataFrame(np.digitize(df, bins), columns=df.columns)
Out[5943]:
   a  b  c
0  1  1  1
1  2  3  3
2  2  1  1
3  1  2  2
4  2  1  2

或者作为
In [5947]: bins2 = np.array([-1, 3, 6, 9])

In [5948]: pd.DataFrame(np.digitize(df, bins2, right=True), columns=df.columns)
Out[5948]:
   a  b  c
0  1  1  1
1  2  3  3
2  2  1  1
3  1  2  2
4  2  1  2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接