【问题标题】:How can I fill in missing values in pandas dataframe using conditions on the data?如何使用数据条件填充 pandas 数据框中的缺失值?
【发布时间】:2019-12-13 07:51:05
【问题描述】:

我有一个汽车数据集,必须训练一个模型来预测汽车的价格,但我的疑问在于数据清洗。以下是数据框 car_df 中存在的列:

Data columns (total 17 columns):
Id                     53515 non-null int64
Maker                  53515 non-null object
model                  53515 non-null object
Location               53515 non-null object
Distance               52304 non-null float64
Owner Type             53515 non-null object
manufacture_year       53515 non-null int64
Age of car             53515 non-null int64
engine_displacement    53515 non-null int64
engine_power           52076 non-null float64
body_type              4136 non-null object
Vroom Audit Rating     53515 non-null int64
transmission           53515 non-null object
door_count             53515 non-null object
seat_count             53515 non-null object
fuel_type              53515 non-null object
Price                  53515 non-null float64
dtypes: float64(3), int64(5), object(9)

door_count 和 seat_count 列包含我想用数值替换的术语“无”。我的算法: 如果对于特定的 Maker、model 组合,door_count 为“None”,则用 Maker、model 组合的 door_count 的中值填充它。 例如,如果 Maker 是 Skoda,model 是 Octavia,则算法会找到 door_count 的中位数并填充 none 值。

这是我尝试实现的代码sn-p:

def find_door_count(Maker, model):
    car_df_temp = car_df[car_df['door_count']!='None']
    car_df_temp['door_count'] = car_df_temp['door_count'].astype('int64')
    ans = car_df_temp[(car_df_temp['Maker']==Maker) & (car_df_temp['model']==model)]['door_count'].median()
    return ans

car_df['door_count'].apply(lambda row: find_door_count(row['Maker'], row['model']))

在运行上面的 sn-p 时,我收到以下错误:

----> 1 car_df['door_count'].apply(lambda row: find_door_count(row['Maker'], row['model']))

TypeError:字符串索引必须是整数

你能告诉我哪里出错了吗?

【问题讨论】:

  • 制作一个小型示例数据集并添加预期输出,以便我们直观地看到您想要做什么。询问您的问题,我们可以提供解决方案,而不是为什么您的代码无法正常工作,请查看What is the XY problem?
  • 但这可能会帮助您解决问题,尽管您的代码不是解决此问题的熊猫方式:car_df_temp['door_count'] = car_df_temp['door_count'].astype(int)。所以只需int 而不是'int64'

标签: python pandas analysis


【解决方案1】:

因为您使用语句car_df['door_count'] 选择car_df 中的列door_count,所以您的代码正在调用Series.apply。传递给此方法的函数采用表示 DataFrame 列的 Series 或单个值,而不是您可能认为的 DataFrame 的一行。

我建议您重新考虑要如何解决此问题。 Pandas 经过优化以执行按列操作,而不是迭代行。您声明您希望执行以下操作:

  1. 计算给定品牌和型号的门的中位数。
  2. 用该中位数填充数据集中的空门值。

在 Pandas 中,第一步是 groupby followed by a transform:您要“分组”MakerModel,然后为 door_count 创建一个替换值,即该列的“转换”在那些群体中。假设 'door_count' 的值是 float 类型,下面是它在代码中的样子:

car_df['median_door_counts'] = car_df.groupby(['Maker', 'Model'])['door_count'].transform('median')  # perform the transformation

这是一个实际的例子:

import pandas as pd
import numpy as np

car_df = pd.DataFrame({"Maker": ["Ford", "Tesla", "GM"] * 4,
                       "Model": ["Pinto", "S", "Sierra", "Fiesta", "X", "Volt"] * 2, 
                       "door_count": np.random.randint(0, 4, size=12, dtype="float")})

car_df['door_count'] = car_df['door_count'].astype(float)     # allow door_count to be nan
car_df.loc[car_df['door_count'] == 0, 'door_count'] = np.nan  # generate some nans

car_df['median_door_counts'] = car_df.groupby(['Maker', 'Model'])['door_count'].transform('median')
print(car_df)
#     Maker   Model  door_count  median_door_counts
# 0    Ford   Pinto         NaN                 NaN
# 1   Tesla       S         2.0                 2.0
# 2      GM  Sierra         2.0                 2.0
# 3    Ford  Fiesta         2.0                 2.0
# 4   Tesla       X         2.0                 2.5
# 5      GM    Volt         1.0                 1.0
# 6    Ford   Pinto         NaN                 NaN
# 7   Tesla       S         NaN                 2.0
# 8      GM  Sierra         NaN                 2.0
# 9    Ford  Fiesta         2.0                 2.0
# 10  Tesla       X         3.0                 2.5
# 11     GM    Volt         1.0                 1.0

您应该查看Series.median 并查看默认参数以了解其工作原理以及我将列转换为浮点值的原因。另外,请注意,福特 Pinto 缺少 door_count 的所有值,因此它们的中值也丢失了。

现在这些中位数是 DataFrame 中的一列,因此您可以使用选择逻辑执行您认为合适的替换操作:

null_door = car_df['door_count'].isnull()  # or whatever logic you want
car_df.loc[null_door, 'door_count'] = car_df.loc[null_door, 'median_door_counts']

我生成的样本数据的结果:

print(car_df)
#     Maker   Model  door_count  median_door_counts
# 0    Ford   Pinto         NaN                 NaN
# 1   Tesla       S         2.0                 2.0
# 2      GM  Sierra         2.0                 2.0
# 3    Ford  Fiesta         2.0                 2.0
# 4   Tesla       X         2.0                 2.5
# 5      GM    Volt         1.0                 1.0
# 6    Ford   Pinto         NaN                 NaN
# 7   Tesla       S         2.0                 2.0
# 8      GM  Sierra         2.0                 2.0
# 9    Ford  Fiesta         2.0                 2.0
# 10  Tesla       X         3.0                 2.5
# 11     GM    Volt         1.0                 1.0

【讨论】:

  • 感谢您的详细解释。真的很感激!!
【解决方案2】:

这就是错误的意思

data[1]  #this will work 
data['string'] #this will not work

【讨论】:

    猜你喜欢
    • 2020-02-28
    • 2018-05-16
    • 2018-12-17
    • 2021-06-17
    • 1970-01-01
    • 1970-01-01
    • 2016-11-16
    • 1970-01-01
    • 2022-01-17
    相关资源
    最近更新 更多