Я использую bnp-paribas-cardif-претензий-управления из Kaggle. Набор данных: https://www.kaggle.com/c/ БНП - Париба - CARDIF - претензия - менеджмент / данные

df=pd.read_csv('F:\\Data\\Paribas_Claim\\train.csv',nrows=5000)

Df.info () дает

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5000 entries, 0 to 4999
Columns: 133 entries, ID to v131
dtypes: float64(108), int64(6), object(19)
memory usage: 5.1+ MB

Мое требование: я пытаюсь заполнить нулевые значения для столбцов с типами данных как int и object. Я пытаюсь заполнить нулями на основе целевого столбца.

Мой код

df_obj = df.select_dtypes(['object','int64']).columns.to_list()
for cols in df_obj:
    df[( df['target'] == 1 )&( df[cols].isnull() )][cols]  = df[df['target'] == 1][cols].mode()
    df[( df['target'] == 0 )&( df[cols].isnull() )][cols]  = df[df['target'] == 0][cols].mode()

Я могу получить вывод в следующем заявлении печати:

df[( df['target'] == 1 )&( df[cols].isnull() )][cols]

Также возможность печатать значения для df[df['target'] == 0][cols].mode(), если я подставлю cols.

Но невозможно заменить нулевые значения значениями режима. Я пробовал df.loc, df.at варианты вместо df[] и df[...] == np.nan вместо df[...].isnull(), но безрезультатно.

Пожалуйста, помогите, если мне нужно внести какие-либо изменения в код. Благодарю.

-1
Madan 7 Июл 2019 в 14:54

4 ответа

Лучший ответ

Здесь проблема заключается в том, что столбцы выбора целых чисел не содержат пропущенных значений (потому что NaN равен float), поэтому не могут быть заменены. Возможное решение - выбрать все числовые столбцы и в цикле установить первое значение режима для условий с помощью DataFrame.loc для предотвращения индексации цепей и Series.iat для возврата только первого значения (режим должен возвращать иногда 2 значения):

df=pd.read_csv('train.csv',nrows=5000)

#only numeric columns
df_obj = df.select_dtypes(np.number).columns.to_list()
#all columns
#df_obj = df.columns.to_list()

#print (df_obj)

for cols in df_obj:
    m1 = df['target'] == 1
    m2 = df['target'] == 0
    df.loc[m1 & (df[cols].isnull()), cols]  = df.loc[m1, cols].mode().iat[0]
    df.loc[m2 & (df[cols].isnull()), cols]  = df.loc[m2, cols].mode().iat[0]

Еще одно решение - заменить отсутствующие значения на {{X0 } } :

for cols in df_obj:
    m1 = df['target'] == 1
    m2 = df['target'] == 0
    df.loc[m1, cols]  = df.loc[m1, cols].fillna(df.loc[m1, cols].mode().iat[0])
    df.loc[m2, cols]  = df.loc[m2, cols].fillna(df.loc[m2, cols].mode().iat[0])

print (df.head())
   ID  target            v1        v2 v3        v4         v5            v6  \
0   3       1  1.335739e+00  8.727474  C  3.921026   7.915266  2.599278e+00   
1   4       1 -9.543625e-07  1.245405  C  0.586622   9.191265  2.126825e-07   
2   5       1  9.438769e-01  5.310079  C  4.410969   5.326159  3.979592e+00   
3   6       1  7.974146e-01  8.304757  C  4.225930  11.627438  2.097700e+00   
4   8       1 -9.543625e-07  1.245405  C  0.586622   2.151983  2.126825e-07   

             v7            v8  ...      v122      v123          v124  v125  \
0  3.176895e+00  1.294147e-02  ...  8.000000  1.989780  3.575369e-02    AU   
1 -9.468765e-07  2.301630e+00  ...  1.499437  0.149135  5.988956e-01    AF   
2  3.928571e+00  1.964513e-02  ...  9.333333  2.477596  1.345191e-02    AE   
3  1.987549e+00  1.719467e-01  ...  7.018256  1.812795  2.267384e-03    CJ   
4 -9.468765e-07 -7.783778e-07  ...  1.499437  0.149135 -9.962319e-07     Z   

           v126          v127      v128  v129      v130          v131  
0  1.804126e+00  3.113719e+00  2.024285     0  0.636365  2.857144e+00  
1  5.521558e-07  3.066310e-07  1.957825     0  0.173913 -9.932825e-07  
2  1.773709e+00  3.922193e+00  1.120468     2  0.883118  1.176472e+00  
3  1.415230e+00  2.954381e+00  1.990847     1  1.677108  1.034483e+00  
4  5.521558e-07  3.066310e-07  0.100455     0  0.173913 -9.932825e-07  

[5 rows x 133 columns]
1
jezrael 7 Июл 2019 в 13:43

У вас нет образцов данных, поэтому я просто приведу методы, которые, по вашему мнению, вы можете использовать для решения своей проблемы.

Попробуйте прочитать ваш DataFrame с na_filter = False таким образом, чтобы ваши столбцы со значениями np.nan или null были заменены пробелами.

Затем во время цикла используйте '' в качестве идентификатора для нулевых значений. Проще помечать, чем пытаться использовать тип значения, которое вы анализируете.

0
Joe 7 Июл 2019 в 12:25

Ваша проблема в этом

df[( df['target'] == 1 )&( df[cols].isnull() )][cols] = ...

НЕ цепляйте индекс, особенно при назначении. См. Почему назначение не выполняется при использовании цепной индексации? в этом разделе doc.

Вместо этого используйте loc:

df.loc[(df['target'] == 1) & (df[cols].isnull()), 
       cols] = df.loc[df['target'] == 1,
                      cols].mode()
0
Quang Hoang 7 Июл 2019 в 13:34

Я думаю, что pd.fillna Должно помочь.

# random dataset
df = pd.DataFrame([[np.nan, 2, np.nan, 0],
                    [3, 2, np.nan, 1],
                    [np.nan, np.nan, np.nan, 5],
                    [np.nan, 3, np.nan, 4]],
                    columns=list('ABCD'))

print(df)

    A   B   C   D
0   NaN 2.0 NaN 0
1   3.0 2.0 NaN 1
2   NaN NaN NaN 5
3   NaN 3.0 NaN 4


Предполагая, что вы хотите заменить отсутствующие значения значением режима данного столбца, я бы просто использовал:

df.fillna({'A':df.A.mode()[0],'B':df.B.mode()[0]})

    A   B   C   D
0   3.0 2.0 NaN 0
1   3.0 2.0 NaN 1
2   3.0 2.0 NaN 5
3   3.0 3.0 NaN 4


Это также будет работать, если вам нужно значение режима из подмножества значений из данного столбца, чтобы заполнить NaN.

# let's add 'type' column

    A   B   C   D   type
0   NaN 2.0     0   1
1   3.0 2.0     1   1
2   NaN NaN     5   2
3   NaN 3.0     4   2

Например, если вы хотите заполнить df['B'] NaN значением режима каждой строки, равным df['type'] 2:

df.fillna({
    'B': df.loc[df.type.eq(2)].B.mode()[0] # type 2 
})

    A   B   C   D   type
0   NaN 2.0 NaN 0   1
1   3.0 2.0 NaN 1   1
2   NaN 3.0 NaN 5   2
3   NaN 3.0 NaN 4   2
       # ↑ this would have been '2.0' hadn't we filtered the column with df.loc[]

0
political scientist 7 Июл 2019 в 13:08