如何将数字数据映射到 Pandas 数据框中的类别/箱中

Posted

技术标签:

【中文标题】如何将数字数据映射到 Pandas 数据框中的类别/箱中【英文标题】:How to map numeric data into categories / bins in Pandas dataframe 【发布时间】:2018-08-29 03:34:24 【问题描述】:

我刚开始用python编码,我的一般编码技能相当生疏:(所以请耐心等待

我有一个熊猫数据框:

它有大约 3m 行。有 3 种年龄单位:Y、D、W 表示年、日和周。任何 1 岁以上的人的年龄单位都是 Y,我想要的第一个分组是

我想创建一个新列 AgeRange 并填充以下范围:

2 - 18 18 - 35 35 - 65 65+

所以我写了一个函数

def agerange(values):
    for i in values:
        if complete.Age_units == 'Y':
            if complete.Age > 1 AND < 18 return '2-18'
            elif complete.Age > 17 AND < 35 return '18-35'
            elif complete.Age > 34 AND < 65 return '35-65'
            elif complete.Age > 64 return '65+'
        else return '< 2'

我想如果我将数据框作为一个整体传递,我会取回我需要的内容,然后可以创建我想要的列:

agedetails['age_range'] = ageRange(agedetails)

但是当我尝试运行第一个代码来创建我得到的函数时:

  File "<ipython-input-124-cf39c7ce66d9>", line 4
    if complete.Age > 1 AND complete.Age < 18 return '2-18'
                          ^
SyntaxError: invalid syntax

显然它不接受 AND - 但我想我在课堂上听说我可以像这样使用 AND?我一定是弄错了,但是这样做的正确方法是什么?

因此,在收到该错误后,我什至不确定传入数据框的方法是否也会引发错误。我猜可能是的。在这种情况下 - 我该如何让它工作?

我希望学习最好的方法,但对我来说最好的方法之一就是保持简单,即使这意味着只需几个步骤即可完成...

【问题讨论】:

@jpp 下面给出了很好的答案 - 还考虑到您的无效语法 AND 应该是小写字母 and 也在 if 语句条件之后您需要使用 : 所以它应该是 if complete.Age &gt; 1 and complete.Age &lt; 18: return '2-18'跨度> 【参考方案1】:

使用 Pandas,您应该避免按行操作,因为这些操作通常涉及低效的 Python 级循环。这里有几个选择。

熊猫:pd.cut

正如@JonClements 建议的那样,您可以为此使用pd.cut,这样做的好处是您的新列变成了Categorical。

您只需定义边界(包括np.inf)和类别名称,然后将pd.cut 应用于所需的数字列。

bins = [0, 2, 18, 35, 65, np.inf]
names = ['<2', '2-18', '18-35', '35-65', '65+']

df['AgeRange'] = pd.cut(df['Age'], bins, labels=names)

print(df.dtypes)

# Age             int64
# Age_units      object
# AgeRange     category
# dtype: object

NumPy:np.digitize

np.digitize 提供了另一种干净的解决方案。这个想法是定义您的边界和名称,创建一个字典,然后将np.digitize 应用于您的年龄列。最后,使用您的字典来映射您的类别名称。

请注意,对于边界情况,下限用于映射到 bin。

import pandas as pd, numpy as np

df = pd.DataFrame('Age': [99, 53, 71, 84, 84],
                   'Age_units': ['Y', 'Y', 'Y', 'Y', 'Y'])

bins = [0, 2, 18, 35, 65]
names = ['<2', '2-18', '18-35', '35-65', '65+']

d = dict(enumerate(names, 1))

df['AgeRange'] = np.vectorize(d.get)(np.digitize(df['Age'], bins))

结果

   Age Age_units AgeRange
0   99         Y      65+
1   53         Y    35-65
2   71         Y      65+
3   84         Y      65+
4   84         Y      65+

【讨论】:

或者...将float('inf')(或np.inf)添加到bins的末尾,然后使用:pd.cut(df.Age, bins, labels=names)...这样您将获得一个分类系列一个字符串... @jpp 这太棒了!感谢您不厌其烦地提供如此清晰和深思熟虑的回复,并且添加带有细节的 bins/pandas 切割方法是锦上添花的完美。这是最简单最优雅的方法,我肯定会使用它,谢谢。我已经在所有看起来的某个地方看到了我正在做一些关于 Bins 的事情 - 但还没有弄清楚如何应用它,当然也不知道它有多容易!再次感谢!

以上是关于如何将数字数据映射到 Pandas 数据框中的类别/箱中的主要内容,如果未能解决你的问题,请参考以下文章

将函数应用于两列并将输出映射到新列[重复]

如何将 Pandas 数据框中的负数替换为零

如何判断 pandas 数据框中的列是不是为 datetime 类型?如何判断一列是不是为数字?

在使用数字列表搜索列后返回数据框中的所有行 - Python/Pandas

比较熊猫数据框中的行值

将 JSON 时间戳字符串转换为 pandas 数据框中的 python 日期