获取 pandas 数据框中每一列的前 k 个元素索引的快速方法
fast way to get index of top-k elements of every column in a pandas dataframe
我有一个非常大的 pandas 数据框,大约有 500,000 列。每列大约有 500 个元素长。对于每一列,我需要检索列中前 k 个元素的(索引,列)位置。
所以,如果 k 等于 2,这是我的数据框:
A B C D
w 4 8 10 2
x 5 1 1 6
y 9 22 25 7
z 15 5 7 2
我想 return:
[(A,y),(A,z),(B,w),(B,y),(C,w),(C,y),(D,x),(D,y)]
请记住,我有大约 500,000 列,因此速度是我最关心的问题。有没有一种合理的方法不会在我的机器上花费整整一周的时间?什么是最快的方式 - 即使它对于我拥有的数据量来说足够快?
感谢您的帮助!
Pandas 有一个高效的 nlargest
操作,您可以使用它比完整排序更快。跨 500,000 列应用仍然需要一段时间。
In [1]: df = pd.DataFrame(data=np.random.randint(0, 100, (200, 500000)),
columns=range(500000), index=range(200))
In [2]: %time np.array([df[c].nlargest(2).index.values for c in df])
Wall time: 2min 57s
Out[2]:
array([[171, 1],
[ 42, 78],
正如@EdChum 指出的那样,您可能不想存储为元组,使用两个数组或其他一些策略会更有效。
我认为 numpy
对此有一个很好的解决方案,速度很快,您可以根据需要格式化输出。
In [2]: df = pd.DataFrame(data=np.random.randint(0, 1000, (200, 500000)),
columns=range(500000), index=range(200))
In [3]: def top_k(x,k):
ind=np.argpartition(x,-1*k)[-1*k:]
return ind[np.argsort(x[ind])]
In [69]: %time np.apply_along_axis(lambda x: top_k(x,2),0,df.as_matrix())
CPU times: user 5.91 s, sys: 40.7 ms, total: 5.95 s
Wall time: 6 s
Out[69]:
array([[ 14, 54],
[178, 141],
[ 49, 111],
...,
[ 24, 122],
[ 55, 89],
[ 9, 175]])
与 pandas 解决方案相比相当快(IMO 更清洁,但我们在这里追求速度):
In [41]: %time np.array([df[c].nlargest(2).index.values for c in df])
CPU times: user 3min 43s, sys: 6.58 s, total: 3min 49s
Wall time: 4min 8s
Out[41]:
array([[ 54, 14],
[141, 178],
[111, 49],
...,
[122, 24],
[ 89, 55],
[175, 9]])
列表的顺序彼此相反(您可以通过在 numpy
版本中反向排序轻松解决此问题)
请注意,在示例中,由于随机 int 生成,我们可能有超过 k
个相等且最大的值,因此返回的索引在所有方法中可能不一致,但所有方法都会产生有效结果(您将获得 k
个与列中的最大值相匹配的索引)
我有一个非常大的 pandas 数据框,大约有 500,000 列。每列大约有 500 个元素长。对于每一列,我需要检索列中前 k 个元素的(索引,列)位置。
所以,如果 k 等于 2,这是我的数据框:
A B C D
w 4 8 10 2
x 5 1 1 6
y 9 22 25 7
z 15 5 7 2
我想 return:
[(A,y),(A,z),(B,w),(B,y),(C,w),(C,y),(D,x),(D,y)]
请记住,我有大约 500,000 列,因此速度是我最关心的问题。有没有一种合理的方法不会在我的机器上花费整整一周的时间?什么是最快的方式 - 即使它对于我拥有的数据量来说足够快?
感谢您的帮助!
Pandas 有一个高效的 nlargest
操作,您可以使用它比完整排序更快。跨 500,000 列应用仍然需要一段时间。
In [1]: df = pd.DataFrame(data=np.random.randint(0, 100, (200, 500000)),
columns=range(500000), index=range(200))
In [2]: %time np.array([df[c].nlargest(2).index.values for c in df])
Wall time: 2min 57s
Out[2]:
array([[171, 1],
[ 42, 78],
正如@EdChum 指出的那样,您可能不想存储为元组,使用两个数组或其他一些策略会更有效。
我认为 numpy
对此有一个很好的解决方案,速度很快,您可以根据需要格式化输出。
In [2]: df = pd.DataFrame(data=np.random.randint(0, 1000, (200, 500000)),
columns=range(500000), index=range(200))
In [3]: def top_k(x,k):
ind=np.argpartition(x,-1*k)[-1*k:]
return ind[np.argsort(x[ind])]
In [69]: %time np.apply_along_axis(lambda x: top_k(x,2),0,df.as_matrix())
CPU times: user 5.91 s, sys: 40.7 ms, total: 5.95 s
Wall time: 6 s
Out[69]:
array([[ 14, 54],
[178, 141],
[ 49, 111],
...,
[ 24, 122],
[ 55, 89],
[ 9, 175]])
与 pandas 解决方案相比相当快(IMO 更清洁,但我们在这里追求速度):
In [41]: %time np.array([df[c].nlargest(2).index.values for c in df])
CPU times: user 3min 43s, sys: 6.58 s, total: 3min 49s
Wall time: 4min 8s
Out[41]:
array([[ 54, 14],
[141, 178],
[111, 49],
...,
[122, 24],
[ 89, 55],
[175, 9]])
列表的顺序彼此相反(您可以通过在 numpy
版本中反向排序轻松解决此问题)
请注意,在示例中,由于随机 int 生成,我们可能有超过 k
个相等且最大的值,因此返回的索引在所有方法中可能不一致,但所有方法都会产生有效结果(您将获得 k
个与列中的最大值相匹配的索引)