1
$\begingroup$

I have data with a lot of NaNs:

train_feat["portarbre"].value_counts(dropna=False)
portarbre
NaN             12958
Libre            6070
Semi-libre       4449
Architecturé      316
Pyramidale          7
Pleureur            4
Name: count, dtype: int64

And a column with no NaNs:

data["adr_secteur"].value_counts(dropna=False)
adr_secteur
6        6958
5        6728
2        6066
3        4249
4        4128
1        3376
38309     180
38151      92
38421      68
38249      41
38158       9
Name: count, dtype: int64

I have other columns also with less NaNs but this one will illustrate the issue. Even though there is a lot of NaNs that the easiest decision would be to just drop the column, filling those 12k of null values can be at least illustrative as an exercise. So I decided to fill the null values with the mode conditioned on the sous_categorie column like the following:

mode_sect_df = train_feat.groupby("portarbre")["adr_secteur"].agg(lambda x: x.mode().max()).reset_index()
mode_sect_df.columns = ["portarbre", "mode_sect"]

for index, row in mode_sect_df.iterrows():

    haut_value = row["portarbre"]
    mode_sect = row["mode_sect"]
    train_feat.loc[train_feat["adr_secteur"] == mode_sect, "portarbre"] = \
        train_feat.loc[train_feat["adr_secteur"] == mode_sect,"portarbre"].fillna(value=haut_value)

That is, I am filling the null values in the portarbre column by taking the mode corresponding to the adr_secteur column:

train_feat.pivot_table(index='adr_secteur', columns='portarbre', aggfunc='size')

portarbre   Architecturé    Libre   Pleureur    Pyramidale  Semi-libre
adr_secteur                  
1           27.0            385.0   NaN          1.0         842.0
2           2691.0          1094.0  1.0          3.0         917.0 
3           20.0            622.0   NaN          NaN         655.0
4           61.0            653.0   NaN          NaN         534.0
5           79.0            1627.0  3120.0       NaN         358.0
6           17.0            4069.0  1.0          3.0         1079.0
38151       NaN             3.0     NaN          NaN         57.0
38158       NaN             NaN     NaN          NaN         7.0

The problem is, after running the code I end with:

 train_feat["portarbre"].value_counts(dropna=False)
 
 portarbre
 Libre           8453
 NaN             4878
 Semi-libre      4449
 Pleureur        3122
 Architecturé    2895
 Pyramidale         7
 Name: count, dtype: int64

I see two problems here (maybe you will see many others):

1- First is the obvious one: not all null values are being filled. In the first count there were 12958 nulls in the "portarbre" column. In the second, after the imputation, there are 4878. I don't see the error in the code. There is no nulls in the column adr_secteur', the one I am using as support to fill the nulls in the adr_secteur`.

2- The second is that more than one category can have the same mode:

mode_stade_dev = train_feat.groupby("hauteurarbre")["stadededeveloppement"].agg(lambda x: x.mode().max()).reset_index()
mode_stade_dev.columns = ["hauteurarbre", "mode_stade"]

    hauteurarbre    mode_stade
0   Moins de 10 m   Arbre adulte
1   Plus de 20 m    Arbre adulte
2   de 10 m à 20 m  Arbre adulte

That is, in the first interaction in the for loop, when selecting Arbre adulte to fill the values, it will fill all nan values with Moins de 10 m and then there will be no more null values to be filled for the other modes. How can I improve this? I don't want to just select the mode of the column to fill all the null values in that column. Maybe this will work for that specific column, but I have others in the dataset that this won't be a good idea (for example, the category of a tree and the stage of its development has different modes depending on the category, but some of them will repeat raising this same issue that I am discussing here).

$\endgroup$

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.