无法更新For循环中的熊猫行

时间:2019-07-07 11:54:45

标签: python pandas dataframe

我正在使用Kaggle的bnp-paribas-cardif-claims-management管理。 数据集:https://www.kaggle.com/c/bnp-paribas-cardif-claims-management/data

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.locdf.at选项代替df[],并使用df[...] == np.nan代替df[...].isnull(),但是没有用。

如果我需要对代码进行任何更改,请提供帮助。谢谢。

4 个答案:

答案 0 :(得分:1)

这里的问题是选择整数列,然后不包含缺少的值(因为NaNfloat),因此无法替换。可能的解决方案是选择所有数字列,并根据条件在循环中设置模式的第一个值,DataFrame.loc用于避免链索引,而Series.iat用于仅返回第一个值(模式有时应返回两个值):

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]

另一种解决方案,其中用Series.fillna替换缺少的值:

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 :(得分:0)

您没有示例数据,所以我只给出我认为可以用来解决问题的方法。

尝试使用na_filter = False读取DataFrame,这样用np.nan或具有null值的列将被替换为空白。

然后,在循环过程中,将''用作空值的标识符。比尝试使用要解析的值的类型更容易标记。

答案 2 :(得分:0)

我认为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'] 2的每一行的模式值填充df['type'] NaN:

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[]

答案 3 :(得分:0)

您的问题是这个

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()