【问题标题】:Assign value of existing column to new columns in pandas based on multiple conditions根据多个条件将现有列的值分配给熊猫中的新列
【发布时间】:2021-09-22 09:33:18
【问题描述】:

我正在尝试根据现有列在 pandas 数据框中创建一个新列。

column1 column2 column3 y1 y2 y3
100 200 300 2020 2021 2022
100 200 300 2021 2022 2023
100 200 300 2019 2020 2021

我想要一个新列 vals,如果 currentyear = y1 和 col2 如果 currentyear = y2,则它的值为 col1

column1 column2 column3 y1 y2 y3 Vals
100 200 300 2020 2021 2022 200
100 200 300 2021 2022 2023 100
100 200 300 2019 2020 2021 300

我正在尝试以下代码:

    def assignvalues(df):
        if df['y1'] == currentyear:
            df['Vals'] = df['col1']
        elif df['y2'] == currentyear:
            df['Vals'] = df['col2']
        elif df['y3'] == currentyear:
            df['Vals'] = df['col3']
df.apply(assignvalues)

它确实创建列但不存储任何值。

【问题讨论】:

    标签: python python-3.x pandas dataframe lambda


    【解决方案1】:

    来自您的DataFrame

    >>> import pandas as pd
    >>> from io import StringIO
    
    >>> df = pd.read_csv(StringIO("""
    ... column1,column2,column3,y1,y2,y3
    ... 100,200,300,2020,2021,2022
    ... 100,200,300,2021,2022,2023
    ... 100,200,300,2019,2020,2021"""))
    >>> df
        column1 column2 column3 y1      y2      y3
    0   100     200     300     2020    2021    2022
    1   100     200     300     2021    2022    2023
    2   100     200     300     2019    2020    2021
    

    还有函数assignvalues,它现在从每个if 的预期列中返回值。例如,我们将currentyear 设置为2021

    >>> def assignvalues(df):
    ...     if df['y1'] == currentyear:
    ...         return df['column1']
    ...     elif df['y2'] == currentyear:
    ...         return df['column2']
    ...     elif df['y3'] == currentyear:
    ...         return df['column3']
    
    >>> currentyear = 2021
    

    我们可以像您一样为df["Vals"] 分配一个apply(),并使用axis=1 参数来获得预期的结果:

    >>> df["Vals"] = df.apply(assignvalues, axis=1)
    >>> df
        column1 column2 column3 y1      y2      y3      Vals
    0   100     200     300     2020    2021    2022    200
    1   100     200     300     2021    2022    2023    100
    2   100     200     300     2019    2020    2021    300
    

    【讨论】:

    • 感谢您的回答。这帮助我通过另外一行获得了解决方案,我将 df 中的 y1 转换为字符串,并将当前年份也作为字符串。最初没有对字符串进行类型转换,它仍然返回空行。例如:df['y2']=df.y2.astype(str)
    【解决方案2】:

    你可以使用np.select()来加快执行速度,如下:

    import numpy as np
    
    currentyear = pd.to_datetime('now').year
    
    condlist = [df['y1'] == currentyear, 
                df['y2'] == currentyear, 
                df['y3'] == currentyear]
    
    choicelist = [df['column1'],
                  df['column2'],
                  df['column3']]            
    
    df['Vals'] = np.select(condlist, choicelist, default=np.nan)
    

    如果当前年份不匹配,则默认值为NaN,您可以通过修改default=参数将其设置为0或您选择的其他值。

    结果:

    print(df)
    
       column1  column2  column3    y1    y2    y3  Vals
    0      100      200      300  2020  2021  2022   200
    1      100      200      300  2021  2022  2023   100
    2      100      200      300  2019  2020  2021   300
    

    【讨论】:

    • 感谢您的回答。我之前也试过这个并且遇到了同样的问题,请让我知道我在做什么。我收到以下错误消息:ValueError: shape mismatch: objects cannot be broadcast to a single shape 如果使用它比 if else 条件语句更快,请告诉我。谢谢
    • @user1855463 .apply() 函数是底层的 Python 循环。它不像 numpy 或其他已使用 C 或 CPython 代码优化以使其运行更快的 Pandas 矢量化操作那样优化。
    • @user1855463 对于您的错误,您的实际数据与示例数据有何不同?
    • 原文结构与示例相同,只是 col1/2/3 有浮点值(但可以根据需要转换为 int)
    • 非常感谢您的帮助:)
    猜你喜欢
    • 2023-02-15
    • 2023-01-11
    • 1970-01-01
    • 1970-01-01
    • 2017-12-18
    • 1970-01-01
    • 2018-12-02
    • 2020-04-09
    • 2021-09-03
    相关资源
    最近更新 更多