Python 有没有按功能划分的numpy组?
numpy中是否有任何函数可以将此数组按第一列向下分组 我在网上找不到好答案Python 有没有按功能划分的numpy组?,python,arrays,numpy,Python,Arrays,Numpy,numpy中是否有任何函数可以将此数组按第一列向下分组 我在网上找不到好答案 >>> a array([[ 1, 275], [ 1, 441], [ 1, 494], [ 1, 593], [ 2, 679], [ 2, 533], [ 2, 686], [ 3, 559], [ 3, 219], [ 3, 455],
>>> a
array([[ 1, 275],
[ 1, 441],
[ 1, 494],
[ 1, 593],
[ 2, 679],
[ 2, 533],
[ 2, 686],
[ 3, 559],
[ 3, 219],
[ 3, 455],
[ 4, 605],
[ 4, 468],
[ 4, 692],
[ 4, 613]])
想要的输出:
array([[[275, 441, 494, 593]],
[[679, 533, 686]],
[[559, 219, 455]],
[[605, 468, 692, 613]]], dtype=object)
产出:
array([[275, 441, 494, 593], [679, 533, 686], [559, 219, 455],
[605, 468, 692, 613]], dtype=object)
该软件包(免责声明:我是它的作者)旨在填补numpy的这一空白。numpy索引中的所有操作都是完全矢量化的,在创建此库的过程中没有O(n^2)算法受到损害
import numpy_indexed as npi
npi.group_by(a[:, 0]).split(a[:, 1])
请注意,通常更有效的方法是直接计算这些组的相关属性(即,group_by(keys).mean(value)),而不是首先拆分为一个列表/锯齿数组。受其启发,但没有他的库,并使用数组的第一列总是在增加的事实(如果不是,则首先使用a=a[a]进行排序)[:,0].argsort()]
)
我没有“计时”,但这可能是解决问题的更快方法:
- 没有python本机循环
- 结果列表是numpy数组,如果您需要对其执行其他numpy操作,则不需要进行新的转换
- 类似O(n)的复杂性
[array([275,441,494,593])、array([679,533,686])、array([559,219,455])、array([605,468,692,613])]
Numpy在这里不是很方便,因为所需的输出不是整数数组(它是列表对象的数组)
我建议使用纯Python的方式
from collections import defaultdict
%%timeit
d = defaultdict(list)
for key, val in a:
d[key].append(val)
10.7 µs ± 156 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
# result:
defaultdict(list,
{1: [275, 441, 494, 593],
2: [679, 533, 686],
3: [559, 219, 455],
4: [605, 468, 692, 613]})
…或者说:
import pandas as pd
%%timeit
df = pd.DataFrame(a, columns=["key", "val"])
df.groupby("key").val.apply(pd.Series.tolist)
979 µs ± 3.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
# result:
key
1 [275, 441, 494, 593]
2 [679, 533, 686]
3 [559, 219, 455]
4 [605, 468, 692, 613]
Name: val, dtype: object
简化并考虑HS星云的注释,可以使用return\u index=True
而不是return\u counts=True
,并去掉cumsum
:
np.split(a[:,1], np.unique(a[:,0], return_index = True)[1])[1:]
输出
[array([275, 441, 494, 593]),
array([679, 533, 686]),
array([559, 219, 455]),
array([605, 468, 692, 613])]
给定X作为要分组的项目数组,y(1D数组)作为相应的组,以下函数使用numpy进行分组: 因此,
groupby(a[:,1],a[:,0])
返回
[array([275,441,494,593]),array([679,533,686]),array([559,219,455]),array([605,468,692,613])
我们可能会发现生成dict也很有用:
def groupby(X):
X = np.asarray(X)
x_uniques = np.unique(X)
return {xi:X[X==xi] for xi in x_uniques}
让我们试一下:
X=[1,1,2,2,3,3,3,3,4,5,6,7,7,8,9,9,1,1,1]
groupby(X)
Out[9]:
{1: array([1, 1, 1, 1, 1]),
2: array([2, 2]),
3: array([3, 3, 3, 3]),
4: array([4]),
5: array([5]),
6: array([6]),
7: array([7, 7]),
8: array([8]),
9: array([9, 9])}
请注意,这本身并不是非常引人注目的-但是如果我们将X
作为对象或命名为tuple
,然后提供一个groupby
函数,它会变得更有趣。稍后会将其放进去。晚到派对上,但无论如何。如果您不仅计划对数组进行分组,而且还想对它们进行操作像是求和、均值等等,而且你这样做的速度很快,你也可能需要考虑。所有这些组操作都被优化了,并且用NUBA来实现。它们很容易胜过其他提到的解决方案。
from numpy\u groupies.aggregate\u numpy import aggregate
聚合(a[:,0],a[:,1],“数组”,填充值=[])
>>>数组([array([],dtype=int64),数组([275441494593]),
数组([679533686]),数组([559219455]),
数组([605468692613]),数据类型=对象)
合计(a[:,0],a[:,1],“总和”)
>>>数组([018031898123378])
要得到完全相同的答案,因为他希望数组([[x]代表x在[list(a[a[:,0]==i,1])代表i在n]])
注意这个解决方案需要O(n^2)操作,这使得它非常低效。使用np.unique
而不是unique
来清除你的代码。工作得很好。尽管我不明白“1”是什么意思在列表中扮演角色(a[a[:,0]==i,1])
statement@partizanos,因为第1栏中的项目应该分组。谢谢。我的意思是,使用On2算法本质上是痛苦的,即使对所说的算法本身也是如此。但是,是的,我想你必须假设On2算法也自我意识到它的劣势,这句话才有意义(n^2)
算法受到了伤害“。你为什么要对他们“友好”呢?相反,你要伤害他们:强迫他们“变得更瘦”如果第一列没有排序怎么办?我们可以将排序与创建组结合起来吗?@Vidaka.sort(axis=0)
会按第一列对数组进行排序(假设索引存储在那里)@ns63sr什么是idx
?此答案不会产生正确的输出。如果您设置idx=a[:,0]
,使完整代码np.split(a[:,1],np.unique(a[:,0],return_index=True)[1:]
很好的解决方案,但它有一个限制。如果缺少索引,这就不起作用(比如2)。它只会返回一个3项长的列表,但由于缺少一些索引,您将无法通过索引访问新列表。有没有办法为不存在的索引返回一个空列表?pandas
performance hit有点残酷。不知道datatable
是否可以得到这个很好的答案。而且很容易记住r!好吧,第二个可能没那么多。这又增加了我的技巧。你基于一列对2d数组进行排序的方法不正确。请使用a=a[a.T[0,:].argsort()]
instead.true!这种排序是在第二列中进行的。我编辑了答案。谢谢当您使用numpy时,返回python dicts通常会大大降低速度。如果您使用较大的数组,请坚持使用numpy功能。当然-但通常足够多的任务都是“小数据”.如果任务比@vincentj的答案更大——我已经投票并发表了评论——效果会更好。但这并不完全是言外之意
[array([275, 441, 494, 593]),
array([679, 533, 686]),
array([559, 219, 455]),
array([605, 468, 692, 613])]
def groupby(X, y):
y = np.asarray(y)
X = np.asarray(X)
y_uniques = np.unique(y)
return [X[y==yi] for yi in y_uniques]
def groupby(X):
X = np.asarray(X)
x_uniques = np.unique(X)
return {xi:X[X==xi] for xi in x_uniques}
X=[1,1,2,2,3,3,3,3,4,5,6,7,7,8,9,9,1,1,1]
groupby(X)
Out[9]:
{1: array([1, 1, 1, 1, 1]),
2: array([2, 2]),
3: array([3, 3, 3, 3]),
4: array([4]),
5: array([5]),
6: array([6]),
7: array([7, 7]),
8: array([8]),
9: array([9, 9])}