【发布时间】:2019-11-16 22:35:33
【问题描述】:
我有一个如下所示的数据框:
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
【问题讨论】:
-
为什么
4,5在第2组6? -
@Erfan:因为来自第 1 组的对
(3,2)已被指定为label 5。对(4, 5)紧随其后,并已分配给label 6 -
这对您没有帮助,因为您正在对多个列进行排序并希望将相同的值分组到相同的组中,但相关的函数是
df.x.argsort(),它为您提供了可以放置的索引按顺序列(将-1分配给nan值)。
标签: python pandas numpy tuples