Pandas dfの欠損の補完を検討しています。
dfは、aからdのgroup、各groupに1から5のx値、
各x値に対して欠損を含むy値から構成されています。
group毎にスライスし、各行に対して、
NaN値が有れば、他のxとy値によって補完値yを計算し、
新たな補完値列に値を代入、flag列に真値として1を代入、
実数が有れば、そのまま実数値を補完列に代入、
flag列に偽値として0を代入します。
2番目以降のgroupに対して、補完値が計算できません。
コード内にdfの内容を出力させましたが、
2番目以降のdfが空になっています。
dfのviewではなくcopyを取るなどの工夫は効果が有りませんでした。
python
1import pandas as pd 2import numpy as np 3 4df_all = pd.DataFrame( 5 data = [['a', 1, np.nan], 6 ['a', 2, 1.0], 7 ['a', 3, 3.0], 8 ['a', 4, np.nan], 9 ['a', 5, 2.0], 10 ['b', 1, 1.0], 11 ['b', 2, np.nan], 12 ['b', 3, 3.0], 13 ['b', 4, 3.0], 14 ['b', 5, np.nan], 15 ['c', 1, np.nan], 16 ['c', 2, 2.0], 17 ['c', 3, np.nan], 18 ['c', 4, 3.0], 19 ['c', 5, 1.0], 20 ['d', 1, 2.0], 21 ['d', 2, np.nan], 22 ['d', 3, 4.0], 23 ['d', 4, np.nan], 24 ['d', 5, 2.0]], 25 columns=['group', 'x', 'y']) 26 27print(df_all) 28 29def split_merge(df): 30 groups = df['group'].unique() 31 print('groups: {}'.format(groups)) 32 df_out = df[:1] 33 for k in range(len(groups)): 34 df = df[5*k:5*(k+1)].copy() 35 print() 36 print('df length: {} of {} in split roop {}'.format(len(df), df['group'].unique(), k)) 37 df_temp = interpolate(df) 38 df_out= pd.concat([df_out, df_temp]) 39 df_out = df_out[1:] 40 df_out['flag'] = df_out['flag'].astype('int8') 41 return df_out 42 43def interpolate(df): 44 df['cal_y'] = np.nan * len(df) 45 df['flag'] = np.nan * len(df) 46 print('---splited df in interpolate function---') 47 print('df length: {}'.format(len(df))) 48 for i in range(len(df)): 49 if pd.isna(df.at[i,'y']): 50 #print('---splited df in interpolate function---') 51 print('Detected na at raw {}'.format(i)) 52 df.at[i,'cal_y'] = calculate(i, df) 53 df.at[i,'flag'] = 1 54 else: 55 df.at[i,'cal_y'] = df.at[i,'y'] 56 df.at[i,'flag'] = 0 57 return df 58 59def calculate(i, df): 60 sum_wj = 0 61 sum_wjyj = 0 62 for j in range(len(df)): 63 xi = df.at[i,'x'] 64 xj, yj = df.at[j,'x'], df.at[j,'y'] 65 if (j!=i) & (pd.notna(yj)): 66 wj = 1 / (np.sqrt((xj - xi)**2)) 67 wjyj = wj * yj 68 else: 69 wj = 0 70 wjyj = 0 71 sum_wj += wj 72 sum_wjyj += wjyj 73 yi = sum_wjyj / sum_wj 74 return yi 75 76start = 0 77group_count = 2 78df = df_all[5*start:5*(start + group_count)].copy() 79print(df) 80 81 82df_out = split_merge(df) 83df_out
回答3件
あなたの回答
tips
プレビュー