我有这样的数据框:
azimuth id
15 100
15 1
15 100
150 2
150 100
240 3
240 100
240 100
350 100
我需要填充的是方位角最接近的行中的100个值: 所需的输出:
azimuth id
15 1
15 1
15 1
150 2
150 2
240 3
240 3
240 3
350 1
350接近15,因为这是一个圆(角度表示)。差是25。
我所拥有的:
def mysubstitution(x):
for i in x.index[x['id'] == 100]:
i = int(i)
diff = (x['azimuth'] - x.loc[i, 'azimuth']).abs()
for ind in diff.index:
if diff[ind] > 180:
diff[ind] = 360 - diff[ind]
else:
pass
exclude = [y for y in x.index if y not in x.index[x['id'] == 100]]
closer_idx = diff[exclude]
closer_df = pd.DataFrame(closer_idx)
sorted_df = closer_df.sort_values('azimuth', ascending=True)
try:
a = sorted_df.index[0]
x.loc[i, 'id'] = x.loc[a, 'id']
except Exception as a:
print(a)
return x
大多数情况下都可以,但是我想有一些更简单的解决方案。
谢谢。
答案 0 :(得分:1)
我试图分两步实现该功能。首先,对于每个方位角,我将保存其id值(对于非100的值)的另一个数据框进行了分组。
然后,使用此数组,我实现了replaceAzimuth
函数,该函数获取数据帧中的每一行,首先检查该值是否已存在。如果是这样,它将直接替换它。否则,它将用分组数据帧中最接近的azimuth
值替换id值。
这里是实现:
df = pd.DataFrame([[15,100],[15,1],[15,100],[150,2],[150,100],[240,3],[240,100],[240,100],[350,100]],columns=['azimuth','id'])
df_non100 = df[df['id'] != 100]
df_grouped = df_non100.groupby(['azimuth'])['id'].min().reset_index()
def replaceAzimuth(df_grouped,id_val):
real_id = df_grouped[df_grouped['azimuth'] == id_val['azimuth']]['id']
if real_id.size == 0:
df_diff = df_grouped
df_diff['azimuth'] = df_diff['azimuth'].apply(lambda x: min(abs(id_val['azimuth'] - x),(360 - id_val['azimuth'] + x)))
id_val['id'] = df_grouped.iloc[df_diff['azimuth'].idxmin()]['id']
else:
id_val['id'] = real_id
return id_val
df = df.apply(lambda x: replaceAzimuth(df_grouped,x), axis = 1)
df
对我来说,代码似乎可以提供您所显示的输出。但是不确定是否在所有情况下都可以使用!
答案 1 :(得分:1)
首先将所有ID设置为nan(如果它们是100)。
df.id = np.where(df.id==100, np.nan, df.id)
然后成对计算角度差异,并找到最接近的ID来填充nans。
df.id = df.id.combine_first(
pd.DataFrame(np.abs(((df.azimuth.values[:,None]-df.azimuth.values) +180) % 360 - 180))
.pipe(np.argsort)
.applymap(lambda x: df.id.iloc[x])
.apply(lambda x: x.dropna().iloc[0], axis=1)
)
df
azimuth id
0 15 1.0
1 15 1.0
2 15 1.0
3 150 2.0
4 150 2.0
5 240 3.0
6 240 3.0
7 240 3.0
8 350 1.0