我有一个看起来像这样的数据框:
df = pd.DataFrame({'group':[1,1,1,1,1,2,2,2,2,3,3,4,4],
'x':[np.nan,np.nan,3,np.nan,2,np.nan,3,3,4,2,1,1,3],
'y':[np.nan,np.nan,2,np.nan,1,np.nan,1,1,5,1,5,1,1]})
group x y
1 nan nan
1 nan nan
1 3.0 2.0
1 nan nan
1 2.0 1.0
2 nan nan
2 3.0 1.0
2 3.0 1.0
2 4.0 5.0
3 2.0 1.0
3 1.0 5.0
4 1.0 1.0
4 3.0 1.0
[基本上,可以说我有4个组,每个组包含具有x,y坐标的点。点可以具有相同的坐标。例如,(3,1)在组2和组4中存在(两次)。此外,如果x为nan,则y也应为nan
我想为每对(x,y)分配相对于元组排序列表的对应位置。如果x=y=nan
,则应返回零。因此输出应为:
group x y label_global
1 nan nan 0
1 nan nan 0
1 3.0 2.0 5
1 nan nan 0
1 2.0 1.0 3
2 nan nan 0
2 3.0 1.0 4
2 3.0 1.0 4
2 4.0 5.0 6
3 2.0 1.0 3
3 1.0 5.0 2
4 1.0 1.0 1
4 3.0 1.0 4
我所做的是以下:
centroids = sorted(set([x for x in zip(df.dropna().x.values, df.dropna().y.values)]))
df['label_global'] = [centroids.index(d) + 1 if d[1]==d[1] else 0 for d in zip(df.x.values, df.y.values)]
请问有更好的方法吗?我的数据框长约200万行,大约需要3分钟才能完成任务
[作为旁注:在最后的列表理解中,表达式if d[1]==d[1] else
用于过滤具有nan
的元组,因为np.nan==np.nan
的值为False
。我最初尝试使用if np.nan not in d else
,即:
df['label_global'] = [centroids.index(d) + 1 if np.nan not in d else 0 for d in zip(df.x.values, df.y.values)]
但是那不起作用,我也不知道为什么。返回值错误:
ValueError: (nan, nan) is not in list
对我来说,这表明if else
循环无效。任何见解都非常欢迎。
我觉得还有些奇怪
[(np.nan, np.nan)==(np.nan, np.nan)
返回True
甚至
[(np.nan,)==(np.nan,)
返回True
但是
[np.nan==np.nan
返回False
df['label_global'] = df.sort_values(['x','y'], na_position='first') \
[['x','y']].fillna(0).diff().ne([0,0]).any(1).cumsum()-1
group x y label_global
0 1 NaN NaN 0
1 1 NaN NaN 0
2 1 3.0 2.0 5
3 1 NaN NaN 0
4 1 2.0 1.0 3
5 2 NaN NaN 0
6 2 3.0 1.0 4
7 2 3.0 1.0 4
8 2 4.0 5.0 6
9 3 2.0 1.0 3
10 3 1.0 5.0 2
11 4 1.0 1.0 1
12 4 3.0 1.0 4