【问题标题】:How can I set a category using the return value of apply() function in pandas?如何使用 pandas 中 apply() 函数的返回值设置类别?
【发布时间】:2018-12-14 17:41:06
【问题描述】:

提前感谢您的阅读。

首先,我使用 python 3.7 和 pandas 0.23.4 和 numpy 1.15。

如果我设置一个分类列,如 df.at[(...), col] = 'category' 它工作得很好。

如下例所示,如果我从 apply() 函数中设置了一个类别,则该列变为 'object' dtype。

如何在 pandas 中使用 apply() 函数的返回值来设置类别?

<pre>
import pandas as pd
import numpy as np

phones = [5551234,5551235,5551236,5551237,5551238,5551239,5551240,5551241,5551242,5551243,5551244,5551245,5551246]

dates = ['01/01/2018','01/07/2017','01/01/2017','01/07/2016','01/01/2016','01/07/2015','01/01/2015','01/07/2014', '01/01/2014','01/07/2013','01/01/2013','01/07/2012','01/01/2012']

df = pd.DataFrame({'PHONE': phones, 'DATE': dates})

df['DATE'] = pd.to_datetime(df['DATE'], format='%d/%m/%Y', errors='coerce')

age_cats = pd.Categorical([], categories=['hot', 'warm', 'cold', 'old', 'ignored'])

df['AGE'] = pd.Series(age_cats)

df.info()
class 'pandas.core.frame.DataFrame'
RangeIndex: 13 entries, 0 to 12
Data columns (total 3 columns):
PHONE    13 non-null int64
DATE     13 non-null datetime64[ns]
AGE      0 non-null category
dtypes: category(1), datetime64[ns](1), int64(1)
memory usage: 501.0 bytes


def get_age(_date):
    if pd.isnull(_date):
        return 'old'

    today = pd.Timestamp.today()
    d = today.day

    if today.month == 2 and d == 29:
        d = 28
    y1 = pd.Timestamp(today.year -1, today.month, d)
    y2 = pd.Timestamp(today.year -2, today.month, d)
    y3 = pd.Timestamp(today.year -3, today.month, d)
    y4 = pd.Timestamp(today.year -4, today.month, d)
    y5 = pd.Timestamp(today.year -5, today.month, d)

    if today &lt _date:
        raise Exception('Future dates mean there is a bug.')
    if y1 &lt _date and _date &lt= today:
        return 'hot'
    elif y3 &lt _date and _date &lt= y1:
        return 'warm'
    elif y5 &lt _date and _date &lt= y3:
        return 'cold'
    else:
        return 'old'

df.at[:, 'AGE'] = df.DATE.apply(get_age)
df.info()

class 'pandas.core.frame.DataFrame'
RangeIndex: 13 entries, 0 to 12
Data columns (total 3 columns):
PHONE    13 non-null int64
DATE     13 non-null datetime64[ns]
AGE      13 non-null object
dtypes: datetime64[ns](1), int64(1), object(1)
memory usage: 392.0+ bytes
</pre>

我添加了与第一列相同类别的第二个 AGE2 列。 我在循环过程中使用了相同的函数,并且没有覆盖 categoricaal dtype。

我使用 apply() 函数是不是错了?

df['AGE2'] = pd.Series(age_cats)

for i, r in df.iterrows():
    df.loc[[i],'AGE2'] = get_age(r['DATE'])

df.info()

class 'pandas.core.frame.DataFrame'
RangeIndex: 13 entries, 0 to 12
Data columns (total 4 columns):
PHONE    13 non-null int64
DATE     13 non-null datetime64[ns]
AGE      13 non-null object
AGE2     13 non-null category
dtypes: category(1), datetime64[ns](1), int64(1), object(1)
memory usage: 605.0+ bytes

【问题讨论】:

    标签: python python-3.x pandas apply categories


    【解决方案1】:

    您为什么不在Series 对象上使用astype 以下列方式执行此操作:

    df['AGE'] = df.DATE.apply(get_age).astype('category', ordered=True, categories=['old', None])
    

    【讨论】:

    • 我会试试的。我刚回来发帖说可能 apply() 应该归咎于丢失的分类问题。
    • 嘿伙计。我认为问题是 dates = pd.date_range(pd.Timestamp.today(), periods=12, freq='-6M') years = list(range(2018, 2010, -1)) # df = pd.DataFrame({'date' : dates}) df['year'] = pd.Series(pd.Categorical([], categories=years)) df['year2'] = pd.Series(pd.Categorical([], categories=years)) df.loc[df.index, 'year'] = df.date.dt.year # respect categories df.loc[:, 'year2'] = df.date.dt.year # overrides categories
    • 很可能。但是我提出的方法是不够的还是我遗漏了什么。
    • 是的(因为它绝对有效)而不是因为我已经在为性能苦苦挣扎。谢谢,因为无论如何它都有帮助!
    • @umberto_jr:如果我帮助了你,请考虑将答案标记为满意(答案左侧的绿色勾号)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    • 2021-03-16
    • 2019-08-22
    • 2020-08-31
    • 2018-05-28
    • 1970-01-01
    相关资源
    最近更新 更多