【问题标题】:Filling missing values with groupby object on Pandas - Titanic dataset用 Pandas 上的 groupby 对象填充缺失值 - Titanic 数据集
【发布时间】:2020-08-16 02:08:09
【问题描述】:

我已经看到了类似的问题,但没有一个是我的答案,或者我没有看到/理解。我是 ML 的新手,并试图在 Kaggle 上发现具有已知数据集的 numpy、pandas。目前,我在 Titanic 数据集上。我有 2 个不同的数据集:训练和测试。我必须在训练和测试数据集的“年龄”列上填充缺失值。我的标准是我使用训练数据集创建的分组对象。我用“Sex”、“Pclass”和“Title”(来自每个乘客姓名的标题)分组。

grouped = train.groupby(["Sex","Title","Pclass"])
grouped_m = grouped.median()
grouped_m = grouped_m.reset_index()[["Sex","Title","Pclass", "Age"]]

输出是:

    Sex    Title  Pclass   Age
0   female     Miss       1  30.0
1   female     Miss       2  24.0
2   female     Miss       3  18.0
3   female      Mrs       1  40.0
4   female      Mrs       2  32.0
5   female      Mrs       3  31.0
6   female  Officer       1  49.0
7   female  Royalty       1  40.5
8     male   Master       1   4.0
9     male   Master       2   1.0
10    male   Master       3   4.0
11    male       Mr       1  40.0
12    male       Mr       2  31.0
13    male       Mr       3  26.0
14    male  Officer       1  51.0
15    male  Officer       2  46.5
16    male  Royalty       1  40.0

这是我应用于“测试”数据集的“年龄”列的标准。例如:当测试数据集上的一行,Sex = Female,Title = Miss,Pclass= 1,Age = NaN,Nan 值必须填写上面的输出,应该是 Age = 30。

填充前:

train["Age"].isna().sum()

输出是:

177

我试过这个:

train["Age"] = train["Age"].fillna(grouped["Age"].transform("median"))

它完美地填充了火车集上的 NaN 值。

填充后:

train["Age"].isna().sum()

输出是:

0

但是当我将它应用于测试数据集时,它根本没有改变,也没有给出任何错误。 填写前:

test["Age"].isna().sum()

输出是:

86

然后我将函数应用到我在火车数据集上创建的组对象:

test["Age"] = test["Age"].fillna(grouped["Age"].transform("median"))
test["Age"].isna().sum()

输出是:

86

测试数据集上仍然存在 NaN 值。我应该如何应用这个函数来使用我用训练数据集创建的分组对象更改测试数据集上的 NaN 值?

【问题讨论】:

  • grouped 来自分组train,因此当您转换时,索引仅与train 集中的行对齐,并且无法填充test 集中的任何内容。您可以在拆分之前填充,也可以使用grouped["Age"].median()的索引合并值
  • 您能否包含代码来准确重现您的问题?
  • @ALollz ,我尝试将训练和测试数据集组合为“组合”。但是结果仍然是相同的,因为正如您所说的“分组来自分组火车”。我的逻辑是使用训练数据创建一个 groupby 对象,并在测试数据上使用该 groupby 对象,因为训练和测试数据集具有相同的列名。

标签: python pandas


【解决方案1】:

编辑: 正如@ALollz 建议的那样,我使用 DataFrame.merge() 方法合并了数据,显然是可行的。代码如下:

# First filling NaN on train set as I did before.
grouped = train.groupby(["Sex","Title", "Pclass"])
grouped_m = grouped.median().reset_index()[["Sex", "Title", "Pclass", "Age"]]
train["Age"] = train["Age"].fillna(grouped["Age"].transform("median"))

# Then used pd.DataFrame.merge() to apply the same grouped features on the test data.
med = train.groupby(['Sex', 'Pclass', 'Title'], 
                   as_index=False)['Age'].median()
test = test.merge(med, on=['Sex','Pclass','Title'], how='left', suffixes=('','_'))
test['Age'] = test['Age'].fillna(test.pop('Age_'))

谢谢大家!

【讨论】:

    【解决方案2】:

    我们希望填充缺失的年龄数据,而不是仅仅删除缺失的年龄数据行。一种方法是填写所有乘客的平均年龄(估算)。 按乘客等级检查平均年龄。例如:

        import matplotlib.pyplot as plt
        import seaborn as sns
        %matplotlib inline
    
        #Data visualization to see the age difference due to Passenger class
        plt.figure(figsize=(12, 7))
        sns.boxplot(x='Pclass',y='Age',data=train,palette='winter')
    
        def impute_age(cols):
            Age = cols[0]
            Pclass = cols[1]
    
            if pd.isnull(Age):
    
                if Pclass == 1:
                    return 37
    
                elif Pclass == 2:
                    return 29
    
                else:
                    return 24
    
            else:
                return Age
        train['Age'] = train[['Age','Pclass']].apply(impute_age,axis=1)#filling the missing values
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-08
      • 1970-01-01
      • 2016-03-15
      • 1970-01-01
      • 2018-02-03
      • 2020-02-20
      • 2022-11-02
      • 2020-02-28
      相关资源
      最近更新 更多