我正在使用具有以下列的汽车销售数据集:“汽车”,“价格”,“车身”,“里程”,“ engV”,“ engType”,“注册”,“年份”,“型号”,“行驶”

列'drive'和'engType'具有NaN缺失值,我想基于['car','model']的分组依据来计算'drive'的模式,然后该组落在哪里,我想替换NaN值基于此分组依据

我尝试了以下方法:


用于数字数据

carsale ['engV2'] =(carsale.groupby(['car','body','model']))['engV']。transform(lambda x:x.fillna(x.median()))


这很好,可以正确填充/替换数据

用于分类数据

carsale ['driveT'] =(carsale.groupby(['car','model']))['drive']。transform(lambda x:x.fillna(x.mode()))
        carsale ['driveT'] =(carsale.groupby(['car','model']))['drive']。transform(lambda x:x.fillna(pd.Series.mode(x))))


两者都给出相同的结果

python - 为什么Fillna不能按预期方式工作-LMLPHP




这是完整的代码:




# carsale['price2'] = (carsale.groupby(['car','model','year']))['price'].transform(lambda x: x.fillna(x.median()))

# carsale['engV2'] = (carsale.groupby(['car','body','model']))['engV'].transform(lambda x: x.fillna(x.median()))
# carsale['mileage2'] = (carsale.groupby(['car','model','year']))['mileage'].transform(lambda x: x.fillna(x.median()))
# mode = carsale.filter(['car','drive']).mode()
# carsale[['test1','test2']] = carsale[['car','engType']].fillna(carsale.mode().iloc[0])

**carsale.groupby(['car', 'model'])['engType'].apply(pd.Series.mode)**

# carsale.apply()
# carsale
# carsale['engType2'] = carsale.groupby('car').engType.transform(lambda x: x.fillna(x.mode()))

**carsale['driveT'] = carsale.groupby(['car', 'model'])['drive'
        ].transform(lambda x: x.fillna(x.mode()))
carsale['driveT'] = carsale.groupby(['car', 'model'])['drive'
        ].transform(lambda x: x.fillna(pd.Series.mode(x)))**

# carsale[carsale.car == 'Mercedes-Benz'].sort_values(['body','engType','model','mileage']).tail(50)
# carsale[carsale.engV.isnull()]
# carsale.sort_values(['car','body','model'])

**carsale**


从以上两种方法得出的结果相同,只是替换/添加新列driveT中的值与原始列'drive'中的值相同。例如,如果我们在某些索引中包含NaN,那么它在driveT中也显示相同的NaN,而对于其他值也显示相同。

但是对于数值数据,如果我应用中位数,则它会添加/替换正确的值。

因此,实际上不是基于['car','model']组来计算模式,而是针对'drive'中的单个值执行模式,但是如果运行此命令

**carsale.groupby(['car','model'])['engType'].apply(pd.Series.mode)**


这是基于groupby(汽车,型号)的正确计算模式

python - 为什么Fillna不能按预期方式工作-LMLPHP

有人可以帮忙吗?

最佳答案

我的方法是:


使用.groupby()创建一个查找数据框,其中包含每个drive / car组合的model功能的模式。
drive中的汽车/模型的值为null时,编写一个方法在该数据帧中查找模式并为给定的汽车/模型返回该模式。


但是,事实证明,有两个特定于OP数据集的关键情况需要处理:


当特定汽车/模型组合没有模式时(因为该组合的drive列中的所有条目均为NaN)。
当特定的汽车品牌没有模式时。


以下是我遵循的步骤。如果我从问题的示例数据帧的前几行扩展来的示例开始:

carsale = pd.DataFrame({'car': ['Ford', 'Mercedes-Benz', 'Mercedes-Benz', 'Mercedes-Benz', 'Mercedes-Benz', 'Nissan', 'Honda','Renault', 'Mercedes-Benz', 'Mercedes-Benz', 'Toyota', 'Toyota', 'Ferrari'],
                   'price': [15500.000, 20500.000, 35000.000, 17800.000, 33000.000, 16600.000, 6500.000, 10500.000, 21500.000, 21500.000, 1280.000, 2005.00, 300000.000],
                   'body': ['crossover', 'sedan', 'other', 'van', 'vagon', 'crossover', 'sedan', 'vagon', 'sedan', 'sedan', 'compact', 'compact', 'sport'],
                   'mileage': [68.0, 173.0, 135.0, 162.0, 91.0, 83.0, 199.0, 185.0, 146.0, 146.0, 200.0, 134, 123.0],
                   'engType': ['Gas', 'Gas', 'Petrol', 'Diesel', np.nan, 'Petrol', 'Petrol', 'Diesel', 'Gas', 'Gas', 'Hybrid', 'Gas', 'Gas'],
                   'registration':['yes', 'yes', 'yes', 'yes', 'yes', 'yes', 'yes', 'yes', 'yes', 'yes', 'yes', 'yes', 'yes'],
                   'year': [2010, 2011, 2008, 2012, 2013, 2013, 2003, 2011, 2012, 2012, 2009, 2003, 1988],
                   'model': ['Kuga', 'E-Class', 'CL 550', 'B 180', 'E-Class', 'X-Trail', 'Accord', 'Megane', 'E-Class', 'E-Class', 'Prius', 'Corolla', 'Testarossa'],
                   'drive': ['full', 'rear', 'rear', 'front', np.nan, 'full', 'front', 'front', 'rear', np.nan, np.nan, 'front', np.nan],
                  })
carsale

    car               price  body       mileage   engType   registration  year  model       drive
0   Ford            15500.0  crossover     68.0   Gas       yes           2010  Kuga        full
1   Mercedes-Benz   20500.0  sedan        173.0   Gas       yes           2011  E-Class     rear
2   Mercedes-Benz   35000.0  other        135.0   Petrol    yes           2008  CL 550      rear
3   Mercedes-Benz   17800.0  van          162.0   Diesel    yes           2012  B 180       front
4   Mercedes-Benz   33000.0  vagon         91.0   NaN       yes           2013  E-Class     NaN
5   Nissan          16600.0  crossover     83.0   Petrol    yes           2013  X-Trail     full
6   Honda            6500.0  sedan        199.0   Petrol    yes           2003  Accord      front
7   Renault         10500.0  vagon        185.0   Diesel    yes           2011  Megane      front
8   Mercedes-Benz   21500.0  sedan        146.0   Gas       yes           2012  E-Class     rear
9   Mercedes-Benz   21500.0  sedan        146.0   Gas       yes           2012  E-Class     NaN
10  Toyota           1280.0  compact      200.0   Hybrid    yes           2009  Prius       NaN
11  Toyota           2005.0  compact      134.0   Gas       yes           2003  Corolla     front
12  Ferrari        300000.0  sport        123.0   Gas       yes           1988  Testarossa  NaN



创建一个数据框,以显示每个drive / car组合的model功能的模式。

如果汽车/模型组合没有模式(例如,丰田普锐斯所在的行),则填写该特定汽车品牌(丰田)的模式。

但是,如果汽车品牌本身(例如本例中的Ferrari)没有模式,我将为drive功能填充数据集的模式。


def get_drive_mode(x):
    brand = x.name[0]
    if x.count() > 0:
        return x.mode() # Return mode for a brand/model if the mode exists.
    elif carsale.groupby(['car'])['drive'].count()[brand] > 0:
        brand_mode = carsale.groupby(['car'])['drive'].apply(lambda x: x.mode())[brand]
        return brand_mode # Return mode of brand if particular brand/model combo has no mode,
    else:                 # but brand itself has a mode for the 'drive' feature.
        return carsale['drive'].mode() # Otherwise return dataset's mode for the 'drive' feature.

drive_modes = carsale.groupby(['car','model'])['drive'].apply(get_drive_mode).reset_index().drop('level_2', axis=1)
drive_modes.rename(columns={'drive': 'drive_mode'}, inplace=True)
drive_modes

    car             model        drive_mode
0   Ferrari         Testarossa   front
1   Ford            Kuga         full
2   Honda           Accord       front
3   Mercedes-Benz   B 180        front
4   Mercedes-Benz   CL 550       rear
5   Mercedes-Benz   E-Class      rear
6   Nissan          X-Trail      full
7   Renault         Megane       front
8   Toyota          Corolla      front
9   Toyota          Prius        front



编写一种方法,如果给定行中的drive值为NaN,则在给定行中查找给定汽车/型号的drive模式值:


def fill_with_mode(x):
    if pd.isnull(x['drive']):
        return drive_modes[(drive_modes['car'] == x['car']) & (drive_modes['model'] == x['model'])]['drive_mode'].values[0]
    else:
        return x['drive']



将以上方法应用于carsale数据框中的行,以创建driveT功能:


carsale['driveT'] = carsale.apply(fill_with_mode, axis=1)
del(drive_modes)


结果为以下数据框:

carsale

    car               price  body       mileage   engType   registration  year  model       drive   driveT
0   Ford            15500.0  crossover     68.0   Gas       yes           2010  Kuga        full    full
1   Mercedes-Benz   20500.0  sedan        173.0   Gas       yes           2011  E-Class     rear    rear
2   Mercedes-Benz   35000.0  other        135.0   Petrol    yes           2008  CL 550      rear    rear
3   Mercedes-Benz   17800.0  van          162.0   Diesel    yes           2012  B 180       front   front
4   Mercedes-Benz   33000.0  vagon         91.0   NaN       yes           2013  E-Class     NaN     rear
5   Nissan          16600.0  crossover     83.0   Petrol    yes           2013  X-Trail     full    full
6   Honda            6500.0  sedan        199.0   Petrol    yes           2003  Accord      front   front
7   Renault         10500.0  vagon        185.0   Diesel    yes           2011  Megane      front   front
8   Mercedes-Benz   21500.0  sedan        146.0   Gas       yes           2012  E-Class     rear    rear
9   Mercedes-Benz   21500.0  sedan        146.0   Gas       yes           2012  E-Class     NaN     rear
10  Toyota           1280.0  compact      200.0   Hybrid    yes           2009  Prius       NaN     front
11  Toyota           2005.0  compact      134.0   Gas       yes           2003  Corolla     front   front
12  Ferrari        300000.0  sport        123.0   Gas       yes           1988  Testarossa  NaN     front


请注意,在driveT列的第4行和第9行中,drive列中的NaN值已替换为字符串rear,正如我们所期望的那样,它是drive的模式。梅赛德斯E级。

另外,在第11行中,由于没有适用于Toyota Prius汽车/模型组合的模式,因此我们填充了Toyota品牌的模式,即front

最后,在第12行中,由于没有法拉利汽车品牌的模式,因此我们填充整个数据集的drive列的模式,该列也为front

关于python - 为什么Fillna不能按预期方式工作,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54542355/

10-12 18:43