【问题标题】:Pandas conditional fillna based on another column valuesPandas 基于另一列值的条件填充
【发布时间】:2020-11-17 13:38:49
【问题描述】:

我正在处理 bigmart 数据集,我想根据另一列的值替换一列的缺失值,实际上:

     Outlet_Size  sales_bin
0         Medium  3000-4000
1         Medium     0-1000
2         Medium  2000-3000
3            NaN     0-1000
4           High     0-1000
...          ...        ...
8518        High  2000-3000
8519         NaN     0-1000
8520       Small  1000-2000
8521      Medium  1000-2000
8522       Small     0-1000

So if train[“Outlet_Size”] value is a NaN and train[“sales_bin”] is  “0-1000”
train[“Outlet_Size”] value shoud become “Small”
else == Medium

但我真的不知道怎么写,而且我发现的所有信息都让我感到困惑

有可能吗?怎么样?

非常感谢

【问题讨论】:

    标签: python pandas dataframe conditional-statements nan


    【解决方案1】:

    使用Series.isna 创建布尔掩码,然后使用np.where + Series.eq 根据sales_bin 等于0-1000 的条件从SmallMedium 中选择选项:

    m = df['Outlet_Size'].isna()
    df.loc[m, 'Outlet_Size'] = np.where(df.loc[m, 'sales_bin'].eq('0-1000'), 'Small', 'Medium')
    

    结果:

    print(df)
         Outlet_Size  sales_bin
    0         Medium  3000-4000
    1         Medium     0-1000
    2         Medium  2000-3000
    3          Small     0-1000
    4           High     0-1000
    8518        High  2000-3000
    8519       Small     0-1000
    8520       Small  1000-2000
    8521      Medium  1000-2000
    8522       Small     0-1000
    

    【讨论】:

    • 您好 Shubham Sharma,非常感谢您的回答,它奏效了 :)。请问您是否可以在多个条件下使用此方法,我尝试使用 'train.loc[m, 'Outlet_Size'] = np.where(train.loc[m,'sales_bin'].eq(" 0-1000"), "Small", train.loc[m,'sales_bin'].eq("2000-3000"), "High", "Medium")' 但它不起作用。再次,非常感谢。
    • 不行,在这种情况下你必须使用np.select
    • 非常感谢!我会尝试使用 np.select
    【解决方案2】:

    您可以使用pandas.Series.map 代替numpy.where

    pandas.Series.map 对于这些简单的情况似乎更方便,这使得使用字典(比如{'0-1000': 'Small', '2000-3000': 'High'})更容易和明确地进行多重插补。

    numpy.where 旨在处理更多逻辑(例如:如果 a

    步骤:

    1. 使用pandas.Series.isna() 生成掩码以标记缺少“Outlet_Size”的pandas.DataFrame 子集;
    2. 使用映射定义字典,例如从“0-1000”到“小”;
    3. 使用 pandas.Series.map 将定义的字典替换为定义的 pandas.DataFrame 子集中的“Outlet_Size”值作为 args 参数。
    4. 使用pandas.Series.fillna() 捕获未映射的缺失“Outlet_Size”并将其归为默认值。

    例子:

    import pandas as pd
    import numpy as np
    fake_dataframe = pd.DataFrame({
        'Outlet_Size' : ['Medium', 'Medium', 'Medium', np.nan, 'High', 'High', np.nan, 'Small', 'Medium', 'Small', np.nan, np.nan],
        'sales_bin': ['3000-4000', '0-1000', '2000-3000', '0-1000', '0-1000', '2000-3000', '0-1000', '1000-2000', '1000-2000', '0-1000', '2000-3000', '1000-2000']
    })
    missing_mask = fake_dataframe['Outlet_Size'].isna()
    mapping_dict = dict({'0-1000': 'Small'})
    fake_dataframe.loc[missing_mask, 'Outlet_Size'] = fake_dataframe.loc[missing_mask, 'sales_bin'].map(mapping_dict)
    fake_dataframe['Outlet_Size'] = fake_dataframe['Outlet_Size'].fillna('Medium')
    print(fake_dataframe)
       Outlet_Size  sales_bin
    0       Medium  3000-4000
    1       Medium     0-1000
    2       Medium  2000-3000
    3        Small     0-1000
    4         High     0-1000
    5         High  2000-3000
    6        Small     0-1000
    7        Small  1000-2000
    8       Medium  1000-2000
    9        Small     0-1000
    10      Medium  2000-3000
    11      Medium  1000-2000
    

    多重插补示例:

    import pandas as pd
    import numpy as np
    fake_dataframe = pd.DataFrame({
        'Outlet_Size' : ['Medium', 'Medium', 'Medium', np.nan, 'High', 'High', np.nan, 'Small', 'Medium', 'Small', np.nan, np.nan],
        'sales_bin': ['3000-4000', '0-1000', '2000-3000', '0-1000', '0-1000', '2000-3000', '0-1000', '1000-2000', '1000-2000', '0-1000', '2000-3000', '1000-2000']
    })
    missing_mask = fake_dataframe['Outlet_Size'].isna()
    mapping_dict = dict({'0-1000': 'Small', '2000-3000': 'High'})
    fake_dataframe.loc[missing_mask, 'Outlet_Size'] = fake_dataframe.loc[missing_mask, 'sales_bin'].map(mapping_dict)
    fake_dataframe['Outlet_Size'] = fake_dataframe['Outlet_Size'].fillna('Medium')
    print(fake_dataframe)
        Outlet_Size sales_bin
    0   Medium  3000-4000
    1   Medium  0-1000
    2   Medium  2000-3000
    3   Small   0-1000
    4   High    0-1000
    5   High    2000-3000
    6   Small   0-1000
    7   Small   1000-2000
    8   Medium  1000-2000
    9   Small   0-1000
    10  High    2000-3000
    11  Medium  1000-2000
    

    【讨论】:

    • 您好 SuoufianeK,非常感谢您的回答。您的建议似乎很有趣,因为它允许根据多个条件填充 NaN。不幸的是 - 我不知道我是否做错了什么 - 我得到一个错误:'missing = train["Outlet_Size"].isna() mapping_dict = dict({'0-1000': 'Small', '2000-3000 ' : 'High'}) na_value = None ' 然后 'train[missing, 'Outlet_Size'] = train.loc[missing, 'sales_bin'].map(mapping_dict, na_action='Medium') ' 然后 : TypeError: '系列的对象是可变的,因此它们不能被散列
    • 嗨。谢谢您的回答。我刚刚编辑,删除了不必要的 na_action。我还提供了一个使用 dict({'0-1000': 'Small', '2000-3000': 'High'}) 进行多重插补的示例。你有一个错误,因为你忘记了 .loc in train[missing, 'Outlet_Size'] = train.loc[missing, 'sales_bin'].map(mapping_dict)
    • 再次感谢!它工作得很好,帮助我更多地了解熊猫
    【解决方案3】:

    遵循 Shubham Sharma 的建议(使用 np.select)并使用该功能 “Item_Outlet_Sales”而不是“sales_bin”

    所以:

            Outlet_Size  Item_Outlet_Sales
    0         Medium          3735.1380
    1         Medium           443.4228
    2         Medium          2097.2700
    3            NaN           732.3800
    4           High           994.7052
    ...          ...                ...
    8518        High          2778.3834
    8519         NaN           549.2850
    8520       Small          1193.1136
    8521      Medium          1845.5976
    8522       Small           765.6700 
    
        missing = train["Outlet_Size"].isna()
        condlist = [train.loc[missing, "Outlet_Size"] & train.loc[missing,'sales_bin'] <=1000, 
        train.loc[missing, "Outlet_Size"] & train.loc[missing,'sales_bin'] > 1000] 
        choicelist = ["Small", "Medium"] #PS, If I got it well it is possible to add as # many contiontions as wanted, as long condlist and choicelist has the same lenght 
        train.loc[missing, 'Outlet_Size'] = np.select(condlist, choicelist)
        train["Outlet_Size"].value_counts(dropna=False)
    
    Small     4798
    Medium    2793
    High       932
    

    非常感谢您的建议和这个精彩的论坛的存在:)

    【讨论】:

      猜你喜欢
      • 2021-07-17
      • 1970-01-01
      • 2017-05-14
      • 1970-01-01
      • 1970-01-01
      • 2022-01-15
      • 1970-01-01
      • 1970-01-01
      • 2023-03-06
      相关资源
      最近更新 更多