填充来自邻居值的值,该值会在Pandas中填充其他列

时间:2020-01-22 22:24:42

标签: python pandas dataframe

我有这样的数据框:

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

大多数情况下都可以,但是我想有一些更简单的解决方案。

谢谢。

2 个答案:

答案 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