【发布时间】:2017-01-16 16:19:38
【问题描述】:
我在 python 中有一个二维数组的列表。对于每个二维数组,最后一列表示一个 ID。现在我想根据 ID(最后一列)加入(可能是 numpy)数组的行。
因此,例如 ID 为 1 的行应该被连接起来。每个 ID 在每个数组中仅出现一次。此外,ID(最后一列)以及倒数第二列只能写在串联数组的最后(即只写一次)。
如何做到这一点?
【问题讨论】:
我在 python 中有一个二维数组的列表。对于每个二维数组,最后一列表示一个 ID。现在我想根据 ID(最后一列)加入(可能是 numpy)数组的行。
因此,例如 ID 为 1 的行应该被连接起来。每个 ID 在每个数组中仅出现一次。此外,ID(最后一列)以及倒数第二列只能写在串联数组的最后(即只写一次)。
如何做到这一点?
【问题讨论】:
Pandas 有一个很好的 join 方法来处理这个角色。如果您的 id 列是您的 DataFrame 的索引,则最容易使用。假设您的二维数组中有两个是adata 和bdata,它们对应的ID 是a_ids 和b_ids。 (如果您只处理整数数据集,并且您的 id 也是整数,它们可以进入 numpy 数组的最后一列。但通常 numpy 处理浮点值,并且 id 通常是字符串而不是整数。在任何一个中在这些常见情况中,最好甚至有必要保持 id 分开,因为 numpy 数组是同质的。)
import pandas as pd
a = pd.DataFrame(adata, index=a_ids)
b = pd.DataFrame(bdata, index=b_ids)
现在你有类似的东西:
加入:
ab = a.join(b, lsuffix='a', rsuffix='b', how='outer')
产量:
这是一个外连接,意味着它返回所有记录的联合,包括 id 仅出现在一个或另一个数据集中的情况。如果您只想在两个输入上匹配(或者如果您的所有数据集都有相同的 id),您可以使用 how='inner' 进行更紧密的交叉连接。
如果你想要一个 numpy 数组而不是 DataFrame,这很简单:
ab.values
产量:
array([[-0.68185189, 2.06517757, 0.49309249, 0.56342363],
[ 0.18518231, -2.93460494, nan, nan],
[ 0.06447249, -0.30244753, 2.46605889, -0.28043202],
[ 0.62137062, 0.10228747, -0.21668058, -1.07091799],
[-0.37247196, -1.5782334 , nan, nan],
[-1.0523353 , -0.52960419, nan, nan],
[ 0.13638979, 0.92173315, nan, nan]])
对于连接索引:
ab.index.values
给予:
array([1001, 1002, 1003, 1004, 1005, 1006, 1007])
因此,尽管您已熟悉 Pandas 并从其高级连接操作中受益(即使您的数据集大小不同,该操作也有效,但包含的 id 并不完全相同,即使 id 的顺序不同) ,如果你想使用这些值,你就可以回到 NumPy 值中。
最后注意,如果您将 NumPy 用于整数值,那么您的 id 已经作为每个数据集中的最后一列嵌入,只需调整 DataFrame 构造函数以获取如下数据:
a = pd.DataFrame(adata[:, :-1], index=adata[:, -1])
b = pd.DataFrame(bdata[:, :-1], index=bdata[:, -1])
# data ids
# ^ all rows ^ all rows
# ^ all but last col ^ just last col
【讨论】:
这是一个使用pandas 的最小示例,因为最初没有提供数据或代码:
import numpy as np
import pandas as pd
# let the last column in these 2-d arrays be the "ID" column
arr1 = np.array([[0,0,1,1,1], [0,1,0,0,2], [1,1,1,2,3]])
arr2 = np.array([[1,1,1,1,1], [2,1,0,0,2], [2,2,1,2,3]])
df1 = pd.DataFrame(arr1)
df2 = pd.DataFrame(arr2)
# Again, a minimal example, but the column at index 4 in these
# DataFrames is the ID column, so we can merge on 4 to get our result
result = pd.merge(df1, df2, on = 4)
【讨论】:
带有@robot's 样本数据的numpy 版本,使用argsort 按最后一列值收集行:
In [28]: arr1 = np.array([[0,0,1,1,1], [0,1,0,0,2], [1,1,1,2,3]])
In [29]: arr2 = np.array([[1,1,1,1,1], [2,1,0,0,2], [2,2,1,2,3]])
In [30]: arr=np.concatenate((arr1,arr2),axis=0)
In [31]: arr
Out[31]:
array([[0, 0, 1, 1, 1],
[0, 1, 0, 0, 2],
[1, 1, 1, 2, 3],
[1, 1, 1, 1, 1],
[2, 1, 0, 0, 2],
[2, 2, 1, 2, 3]])
In [32]: idx=np.argsort(arr[:,-1])
In [33]: idx
Out[33]: array([0, 3, 1, 4, 2, 5], dtype=int32)
In [34]: arr[idx,:]
Out[34]:
array([[0, 0, 1, 1, 1],
[1, 1, 1, 1, 1],
[0, 1, 0, 0, 2],
[2, 1, 0, 0, 2],
[1, 1, 1, 2, 3],
[2, 2, 1, 2, 3]])
此外,ID(最后一列)以及倒数第二列只能写在串联数组的最后(即只写一次)。
如果我理解正确的话,这个要求对于numpy 是不可能的。数组每行的列数必须相同。使用pandas,您可以构建多级索引,并且大概使用此ID 作为索引级别。
我们需要您自己的样本、输入和结果,才能做得更好。
================
我们可以使用np.split 将排序后的数组分解为具有共同最后一列的数组。我手动选择了[2,4],但如果您有兴趣,可以从数据中得出。
In [39]: np.split(arr[idx,:],[2,4])
Out[39]:
[array([[0, 0, 1, 1, 1],
[1, 1, 1, 1, 1]]),
array([[0, 1, 0, 0, 2],
[2, 1, 0, 0, 2]]),
array([[1, 1, 1, 2, 3],
[2, 2, 1, 2, 3]])]
【讨论】: