【问题标题】:How do you use custom data types in pandas' astype method?如何在 pandas 的 astype 方法中使用自定义数据类型?
【发布时间】:2021-12-28 10:52:25
【问题描述】:

如何在 pandas 的 astype 方法中使用自定义数据类型?或者,如何将函数映射到特定列?

例如,假设我有一个“季度”数据类型:

class Quarter:
    def __init__(self, date):
       self.year = date.year
       self.quarter = date.quarter

   def __repr__(self):
       return f'{self.year} Q{self.quarter}'

我想说:

df.astype({'date':Quarter})

有什么想法吗?

【问题讨论】:

    标签: pandas


    【解决方案1】:

    看来你只是想要什么

    df['date'] = df['date'].map(Quarter)
    

    请注意,您不能将列数据类型更改为自定义类型。包含自定义 python 对象的列(系列)将始终具有通用 object dtype

    class Quarter:
        def __init__(self, date):
           self.year = date.year
           self.quarter = date.quarter
        def __repr__(self):
           return f'{self.year} Q{self.quarter}'
    
    >>> df = pd.DataFrame({
        'date': pd.date_range('01-01-2021', periods=10, freq='2M')
    })
    >>> df['date']
    
    0   2021-01-31
    1   2021-03-31
    2   2021-05-31
    3   2021-07-31
    4   2021-09-30
    5   2021-11-30
    6   2022-01-31
    7   2022-03-31
    8   2022-05-31
    9   2022-07-31
    Name: date, dtype: datetime64[ns]
    
    >>> df['date'] = df['date'].map(Quarter)
    >>> df['date']
    
    0    2021 Q1
    1    2021 Q1
    2    2021 Q2
    3    2021 Q3
    4    2021 Q3
    5    2021 Q4
    6    2022 Q1
    7    2022 Q1
    8    2022 Q2
    9    2022 Q3
    Name: date, dtype: object
    
    # 'date' column data type
    >>> df['date'].dtype
    
    dtype('O')
    
    # data type of each element of 'date' column 
    >>> df['date'].map(type)
    
    0    <class '__main__.Quarter'>
    1    <class '__main__.Quarter'>
    2    <class '__main__.Quarter'>
    3    <class '__main__.Quarter'>
    4    <class '__main__.Quarter'>
    5    <class '__main__.Quarter'>
    6    <class '__main__.Quarter'>
    7    <class '__main__.Quarter'>
    8    <class '__main__.Quarter'>
    9    <class '__main__.Quarter'>
    Name: date, dtype: object
    

    我正在寻找允许方法链接的东西。我可以做df.assign(date = lambda x: x['date'].map(Quarter)),但是多列会变得很混乱

    使用DataFrame.agg:

    >>> df.agg({'date': Quarter})
    
          date
    0  2021 Q1
    1  2021 Q1
    2  2021 Q2
    3  2021 Q3
    4  2021 Q3
    5  2021 Q4
    6  2022 Q1
    7  2022 Q1
    8  2022 Q2
    9  2022 Q3
    

    如果您想就地更改,您可以定义一个通用函数,该函数接收 DataFrame df 和格式为 {'column of df': func_to_apply_to_column} 的字典,类似于 astype,并将每个函数相应地应用于相应的列。要将其与方法链接一起使用,请使用DataFrame.pipe

    def map_columns(df, col_func_dict):
        for col, func in col_func_dict.items():
            df[col] = df[col].map(func)
        return df
    
    >>> df.pipe(map_columns, {'date': Quarter})
    
          date
    0  2021 Q1
    1  2021 Q1
    2  2021 Q2
    3  2021 Q3
    4  2021 Q3
    5  2021 Q4
    6  2022 Q1
    7  2022 Q1
    8  2022 Q2
    9  2022 Q3
    

    【讨论】:

    • 谢谢,虽然这可行,但我正在寻找允许方法链接的东西。我可以做df.assign(date = lambda x: x['date'].map(Quarter)),但多列会变得很混乱。
    • @MycchakaKleinbort 我用这个要求更新了答案。它解决了你的问题吗?
    • 是的,这行得通。我提出了一个新问题,询问什么是最好的 pandas 方法(如果有的话),但是您的自定义代码有效。仅供参考,您正在就地修改 df,但如果我想要不变性,我可以调整它。 stackoverflow.com/questions/70005612/…
    • 如果没有内置方法,我总是可以为 Pandas 注册一个扩展。
    • @MycchakaKleinbort 我过于复杂了,我再次更新了答案。你只需要使用DataFrame.agg。但只选择了映射的列。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-09
    • 2021-03-09
    • 2019-04-15
    • 1970-01-01
    • 1970-01-01
    • 2022-01-09
    • 2013-08-09
    相关资源
    最近更新 更多