Numpy:如何重新排序数组的行以匹配另一个数组的行?
Numpy: How do I reorder the rows of an array to match the rows of another array?
我有两个包含 XYZ 点 A 和 B 的二维数组。
数组 A 的形状为 (796704, 3),是我的原始点云。除了 (0, 0, 0),每个点都是唯一的,但这些无关紧要:
A = [[x_1, y_1, z_1],
[x_2, y_2, z_2],
[x_3, y_3, z_3],
[x_4, y_4, z_4],
[x_5, y_5, z_5],
...]
数组 B 的形状为 (N, 4),是 A (N<796704) 的裁剪版本。
其余点数没有变化,仍然与 A 中的对应点相同。
第四列是每个点的分割值。
B 的行顺序完全随机,不再与 A 匹配。
B = [[x_4, y_4, z_4, 5],
[x_2, y_2, z_2, 12],
[x_6, y_6, z_6, 5],
[x_7, y_7, z_7, 3],
[x_9, y_9, z_9, 3]]
我需要对 B 的行重新排序,使它们与 A 的行具有相同的点,并用零行填充空白:
B = [[0.0, 0.0, 0.0, 0],
[x_2, y_2, z_2, 12],
[0.0, 0.0, 0.0, 0],
[x_4, y_4, z_4, 5],
[0.0, 0.0, 0.0, 0],
[x_6, y_6, z_6, 5],
[x_7, y_7, z_7, 3],
[0.0, 0.0, 0.0, 0],
[x_9, y_9, z_9, 3],
[0.0, 0.0, 0.0, 0],
[0.0, 0.0, 0.0, 0],
[0.0, 0.0, 0.0, 0]
...]
最后 B 的形状应该是 (796704, 4)。
我尝试使用 numpy_indexed 包,就像在 this very similar question 中提出的那样,但这里的问题是 B 不包含 A 的所有点:
import numpy_indexed as npi
B[npi.indices(B[:, :-1], A)]
我不熟悉 numpy,我唯一的解决方案是 for 循环,但这对我的应用程序来说太慢了。有什么快速解决这个问题的方法吗?
Pandas => 重建索引:
import pandas as pd
import numpy as np
A = np.array([[8, 7, 4],
[0, 7, 7],
[4, 7, 0],
[5, 5, 8],
[8, 7, 5]])
B = np.array([[8, 7, 4, 2],
[4, 7, 0, 5],
[8, 7, 5, 6]])
df_B = (pd.DataFrame(B, columns=["x", "y", "z", "seg"])
.set_index(["x", "y", "z"])
.reindex(list(map(tuple, A)))
.reset_index())
df_B.loc[df_B.seg.isna()] = 0
B = df_B.values
print(B)
结果:
array([[8., 7., 4., 2.],
[0., 0., 0., 0.],
[4., 7., 0., 5.],
[0., 0., 0., 0.],
[8., 7., 5., 6.]])
用 numpy 解决你的问题:
案例一
您正在处理数字:
import numpy as np
A = np.array([[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4],
[5, 5, 5],
[6, 6, 6],
[7, 7, 7],
[8, 8, 8],
[9, 9, 9],
[10,10, 10]
])
B = np.array([[4, 4, 4, 5],
[2, 2, 2, 12],
[6, 6, 6, 5],
[7, 7, 7, 3],
[9, 9, 9, 3]])
c = np.insert(A, 3, 0, axis = 1)
d = np.vstack((B,c[np.in1d(c[:,0],B[:,0], invert=True)]*0))
print(d)
Out:
[[ 4 4 4 5]
[ 2 2 2 12]
[ 6 6 6 5]
[ 7 7 7 3]
[ 9 9 9 3]
[ 0 0 0 0] # previously 1, 1, 1, 0
[ 0 0 0 0] # previously 3, 3, 3, 0
[ 0 0 0 0] # previously 5, 5, 5, 0
[ 0 0 0 0] # previously 8, 8, 8, 0
[ 0 0 0 0]] # previously 10, 10, 10, 0
说明:
1º c
将是 A
的副本,新字段带有 0
:
c = np.insert(A, 3, 0, axis = 1)
如果我现在打印 c
我会得到这个:
[[ 1 1 1 0]
[ 2 2 2 0]
[ 3 3 3 0]
[ 4 4 4 0]
[ 5 5 5 0]
[ 6 6 6 0]
[ 7 7 7 0]
[ 8 8 8 0]
[ 9 9 9 0]
[10 10 10 0]]
2º 你用 B
创建一个新数组,c
中不在 B
中的部分乘以 0
。
d = np.vstack((B,c[np.in1d(c[:,0],B[:,0], invert=True)]*0))
2.1 np.vstack((B,_))
在这里我删除了 c
只是为了让您更容易看到 vstack
收到的参数。您有一个包含要连接的两个数组的元组。
2.2 c[np.in1d(c[:,0],B[:,0], invert=True)]*0
而不是传递所有 c
传递 c
selecting c
的 np.in1d(c[:,0],B[:,0], invert=True)
并将其乘以 0
.
2.3 np.in1d(c[:,0],B[:,0], invert=True)
如果我这样做 np.in1d(c[:,0],B[:,0])
我得到一个布尔数组告诉我 c
中的哪个 x_n
也存在于 B
中,如果我设置invert=True
我会找出 c
中的 x_n
不存在于 B
中。 (另一种反转的方法是使用波浪符运算符 ~
,所以 ~np.in1d(c[:,0],B[:,0])
== np.in1d(c[:,0],B[:,0], invert=True)
)
由于除了 0,0,0,0
之外的每个点都是唯一的,因此当我执行 c[np.in1d(c[:,0],B[:,0], invert=True)]
时,我得到:
array([[ 1, 1, 1, 0],
[ 3, 3, 3, 0],
[ 5, 5, 5, 0],
[ 8, 8, 8, 0],
[10, 10, 10, 0]])
如果我乘以 0,我得到:
array([[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]])
所以在 np.vstack((B,c[np.in1d(c[:,0],B[:,0], invert=True)]*0))
中,我连接了 B
和 c
。
作为 B
这个:
array([[ 4, 4, 4, 5],
[ 2, 2, 2, 12],
[ 6, 6, 6, 5],
[ 7, 7, 7, 3],
[ 9, 9, 9, 3]])
和c
上面0
的数组。最后的结果是:
array([[ 4, 4, 4, 5],
[ 2, 2, 2, 12],
[ 6, 6, 6, 5],
[ 7, 7, 7, 3],
[ 9, 9, 9, 3],
[ 0, 0, 0, 0],
[ 0, 0, 0, 0],
[ 0, 0, 0, 0],
[ 0, 0, 0, 0],
[ 0, 0, 0, 0]])
案例二
如果您正在处理字符串和数字,您可以这样做:
import numpy as np
A = np.array([['x_1', 'y_1', 'z_1'],
['x_2', 'y_2', 'z_2'],
['x_3', 'y_3', 'z_3'],
['x_4', 'y_4', 'z_4'],
['x_5', 'y_5', 'z_5'],
['x_6', 'y_6', 'z_6'],
['x_7', 'y_7', 'z_7'],
['x_8', 'y_8', 'z_8'],
['x_9', 'y_9', 'z_9'],
['x_10', 'y_10', 'z_10']
])
B = np.array([['x_4', 'y_4', 'z_4', 5],
['x_2', 'y_2', 'z_2', 12],
['x_6', 'y_6', 'z_6', 5],
['x_7', 'y_7', 'z_7', 3],
['x_9', 'y_9', 'z_9', 3]])
c = np.insert(A, 3, 0, axis = 1)
c[np.in1d(c[:,0],B[:,0], invert=True)] = 0
d = np.vstack((B,c[np.in1d(c[:,0],B[:,0], invert=True)]))
print(d)
Out:
[['x_4' 'y_4' 'z_4' '5']
['x_2' 'y_2' 'z_2' '12']
['x_6' 'y_6' 'z_6' '5']
['x_7' 'y_7' 'z_7' '3']
['x_9' 'y_9' 'z_9' '3']
['0' '0' '0' '0']
['0' '0' '0' '0']
['0' '0' '0' '0']
['0' '0' '0' '0']
['0' '0' '0' '0']]
说明:
1º c
将是 A
的副本,新字段带有 0
:
c = np.insert(A, 3, 0, axis = 1)
如果我现在打印 c
我会得到这个:
[['x_1' 'y_1' 'z_1' '0']
['x_2' 'y_2' 'z_2' '0']
['x_3' 'y_3' 'z_3' '0']
['x_4' 'y_4' 'z_4' '0']
['x_5' 'y_5' 'z_5' '0']
['x_6' 'y_6' 'z_6' '0']
['x_7' 'y_7' 'z_7' '0']
['x_8' 'y_8' 'z_8' '0']
['x_9' 'y_9' 'z_9' '0']
['x_10' 'y_10' 'z_10' '0']]
2º 在B
中不存在的c
字段,我将设置为0
c[np.in1d(c[:,0],B[:,0], invert=True)] = 0
3º d
将是 B
+ 设置为 0
的 c
部分
d = np.vstack((B,c[np.in1d(c[:,0],B[:,0], invert=True)]))
因为在这种情况下,您在同一个数组中处理字符串和数字,所以您不能在 d
处全部乘以 0
。所以你需要将 c
的字段设置为 0
然后 select 0
的字段。
有用链接:
.
Tilde Operator.
我设法使用我在问题中提到的 numpy_indexed 包解决了这个问题。
解决方法:
A = np.array([[8, 7, 4],
[0, 7, 7],
[4, 3, 0],
[5, 5, 8],
[3, 9, 5]])
B = np.array([[3, 9, 5, 6],
[8, 7, 4, 2],
[4, 3, 0, 5]])
# Create a new, zero-filled, array C with length of A
C = np.zeros((A.shape[0], 4))
# Insert B at the beginning of C
C[:B.shape[0], :B.shape[1]] = B
print(C)
Out:
[[3, 9, 5, 6],
[8, 7, 4, 2],
[4, 3, 0, 5],
[0, 0, 0, 0],
[0, 0, 0, 0]]
# Using the numpy_indexed package reorder the rows.
# The last index of C is used as a fill value in case
# a row wasn't found in A thus filling the gaps with [0,0,0,0]
import numpy_indexed as npi
D = C[npi.indices(C[:, :-1], A, missing=-1)]
print(D)
Out:
[[8, 7, 4, 2],
[0, 0, 0, 0],
[4, 3, 0, 5],
[0, 0, 0, 0],
[3, 9, 5, 6]]
我有两个包含 XYZ 点 A 和 B 的二维数组。
数组 A 的形状为 (796704, 3),是我的原始点云。除了 (0, 0, 0),每个点都是唯一的,但这些无关紧要:
A = [[x_1, y_1, z_1],
[x_2, y_2, z_2],
[x_3, y_3, z_3],
[x_4, y_4, z_4],
[x_5, y_5, z_5],
...]
数组 B 的形状为 (N, 4),是 A (N<796704) 的裁剪版本。
其余点数没有变化,仍然与 A 中的对应点相同。
第四列是每个点的分割值。
B 的行顺序完全随机,不再与 A 匹配。
B = [[x_4, y_4, z_4, 5],
[x_2, y_2, z_2, 12],
[x_6, y_6, z_6, 5],
[x_7, y_7, z_7, 3],
[x_9, y_9, z_9, 3]]
我需要对 B 的行重新排序,使它们与 A 的行具有相同的点,并用零行填充空白:
B = [[0.0, 0.0, 0.0, 0],
[x_2, y_2, z_2, 12],
[0.0, 0.0, 0.0, 0],
[x_4, y_4, z_4, 5],
[0.0, 0.0, 0.0, 0],
[x_6, y_6, z_6, 5],
[x_7, y_7, z_7, 3],
[0.0, 0.0, 0.0, 0],
[x_9, y_9, z_9, 3],
[0.0, 0.0, 0.0, 0],
[0.0, 0.0, 0.0, 0],
[0.0, 0.0, 0.0, 0]
...]
最后 B 的形状应该是 (796704, 4)。
我尝试使用 numpy_indexed 包,就像在 this very similar question 中提出的那样,但这里的问题是 B 不包含 A 的所有点:
import numpy_indexed as npi
B[npi.indices(B[:, :-1], A)]
我不熟悉 numpy,我唯一的解决方案是 for 循环,但这对我的应用程序来说太慢了。有什么快速解决这个问题的方法吗?
Pandas => 重建索引:
import pandas as pd
import numpy as np
A = np.array([[8, 7, 4],
[0, 7, 7],
[4, 7, 0],
[5, 5, 8],
[8, 7, 5]])
B = np.array([[8, 7, 4, 2],
[4, 7, 0, 5],
[8, 7, 5, 6]])
df_B = (pd.DataFrame(B, columns=["x", "y", "z", "seg"])
.set_index(["x", "y", "z"])
.reindex(list(map(tuple, A)))
.reset_index())
df_B.loc[df_B.seg.isna()] = 0
B = df_B.values
print(B)
结果:
array([[8., 7., 4., 2.],
[0., 0., 0., 0.],
[4., 7., 0., 5.],
[0., 0., 0., 0.],
[8., 7., 5., 6.]])
用 numpy 解决你的问题:
案例一
您正在处理数字:
import numpy as np
A = np.array([[1, 1, 1],
[2, 2, 2],
[3, 3, 3],
[4, 4, 4],
[5, 5, 5],
[6, 6, 6],
[7, 7, 7],
[8, 8, 8],
[9, 9, 9],
[10,10, 10]
])
B = np.array([[4, 4, 4, 5],
[2, 2, 2, 12],
[6, 6, 6, 5],
[7, 7, 7, 3],
[9, 9, 9, 3]])
c = np.insert(A, 3, 0, axis = 1)
d = np.vstack((B,c[np.in1d(c[:,0],B[:,0], invert=True)]*0))
print(d)
Out:
[[ 4 4 4 5]
[ 2 2 2 12]
[ 6 6 6 5]
[ 7 7 7 3]
[ 9 9 9 3]
[ 0 0 0 0] # previously 1, 1, 1, 0
[ 0 0 0 0] # previously 3, 3, 3, 0
[ 0 0 0 0] # previously 5, 5, 5, 0
[ 0 0 0 0] # previously 8, 8, 8, 0
[ 0 0 0 0]] # previously 10, 10, 10, 0
说明:
1º c
将是 A
的副本,新字段带有 0
:
c = np.insert(A, 3, 0, axis = 1)
如果我现在打印 c
我会得到这个:
[[ 1 1 1 0]
[ 2 2 2 0]
[ 3 3 3 0]
[ 4 4 4 0]
[ 5 5 5 0]
[ 6 6 6 0]
[ 7 7 7 0]
[ 8 8 8 0]
[ 9 9 9 0]
[10 10 10 0]]
2º 你用 B
创建一个新数组,c
中不在 B
中的部分乘以 0
。
d = np.vstack((B,c[np.in1d(c[:,0],B[:,0], invert=True)]*0))
2.1 np.vstack((B,_))
在这里我删除了 c
只是为了让您更容易看到 vstack
收到的参数。您有一个包含要连接的两个数组的元组。
2.2 c[np.in1d(c[:,0],B[:,0], invert=True)]*0
而不是传递所有 c
传递 c
selecting c
的 np.in1d(c[:,0],B[:,0], invert=True)
并将其乘以 0
.
2.3 np.in1d(c[:,0],B[:,0], invert=True)
如果我这样做 np.in1d(c[:,0],B[:,0])
我得到一个布尔数组告诉我 c
中的哪个 x_n
也存在于 B
中,如果我设置invert=True
我会找出 c
中的 x_n
不存在于 B
中。 (另一种反转的方法是使用波浪符运算符 ~
,所以 ~np.in1d(c[:,0],B[:,0])
== np.in1d(c[:,0],B[:,0], invert=True)
)
由于除了 0,0,0,0
之外的每个点都是唯一的,因此当我执行 c[np.in1d(c[:,0],B[:,0], invert=True)]
时,我得到:
array([[ 1, 1, 1, 0],
[ 3, 3, 3, 0],
[ 5, 5, 5, 0],
[ 8, 8, 8, 0],
[10, 10, 10, 0]])
如果我乘以 0,我得到:
array([[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]])
所以在 np.vstack((B,c[np.in1d(c[:,0],B[:,0], invert=True)]*0))
中,我连接了 B
和 c
。
作为 B
这个:
array([[ 4, 4, 4, 5],
[ 2, 2, 2, 12],
[ 6, 6, 6, 5],
[ 7, 7, 7, 3],
[ 9, 9, 9, 3]])
和c
上面0
的数组。最后的结果是:
array([[ 4, 4, 4, 5],
[ 2, 2, 2, 12],
[ 6, 6, 6, 5],
[ 7, 7, 7, 3],
[ 9, 9, 9, 3],
[ 0, 0, 0, 0],
[ 0, 0, 0, 0],
[ 0, 0, 0, 0],
[ 0, 0, 0, 0],
[ 0, 0, 0, 0]])
案例二
如果您正在处理字符串和数字,您可以这样做:
import numpy as np
A = np.array([['x_1', 'y_1', 'z_1'],
['x_2', 'y_2', 'z_2'],
['x_3', 'y_3', 'z_3'],
['x_4', 'y_4', 'z_4'],
['x_5', 'y_5', 'z_5'],
['x_6', 'y_6', 'z_6'],
['x_7', 'y_7', 'z_7'],
['x_8', 'y_8', 'z_8'],
['x_9', 'y_9', 'z_9'],
['x_10', 'y_10', 'z_10']
])
B = np.array([['x_4', 'y_4', 'z_4', 5],
['x_2', 'y_2', 'z_2', 12],
['x_6', 'y_6', 'z_6', 5],
['x_7', 'y_7', 'z_7', 3],
['x_9', 'y_9', 'z_9', 3]])
c = np.insert(A, 3, 0, axis = 1)
c[np.in1d(c[:,0],B[:,0], invert=True)] = 0
d = np.vstack((B,c[np.in1d(c[:,0],B[:,0], invert=True)]))
print(d)
Out:
[['x_4' 'y_4' 'z_4' '5']
['x_2' 'y_2' 'z_2' '12']
['x_6' 'y_6' 'z_6' '5']
['x_7' 'y_7' 'z_7' '3']
['x_9' 'y_9' 'z_9' '3']
['0' '0' '0' '0']
['0' '0' '0' '0']
['0' '0' '0' '0']
['0' '0' '0' '0']
['0' '0' '0' '0']]
说明:
1º c
将是 A
的副本,新字段带有 0
:
c = np.insert(A, 3, 0, axis = 1)
如果我现在打印 c
我会得到这个:
[['x_1' 'y_1' 'z_1' '0']
['x_2' 'y_2' 'z_2' '0']
['x_3' 'y_3' 'z_3' '0']
['x_4' 'y_4' 'z_4' '0']
['x_5' 'y_5' 'z_5' '0']
['x_6' 'y_6' 'z_6' '0']
['x_7' 'y_7' 'z_7' '0']
['x_8' 'y_8' 'z_8' '0']
['x_9' 'y_9' 'z_9' '0']
['x_10' 'y_10' 'z_10' '0']]
2º 在B
中不存在的c
字段,我将设置为0
c[np.in1d(c[:,0],B[:,0], invert=True)] = 0
3º d
将是 B
+ 设置为 0
c
部分
d = np.vstack((B,c[np.in1d(c[:,0],B[:,0], invert=True)]))
因为在这种情况下,您在同一个数组中处理字符串和数字,所以您不能在 d
处全部乘以 0
。所以你需要将 c
的字段设置为 0
然后 select 0
的字段。
有用链接:
Tilde Operator.
我设法使用我在问题中提到的 numpy_indexed 包解决了这个问题。
解决方法:
A = np.array([[8, 7, 4],
[0, 7, 7],
[4, 3, 0],
[5, 5, 8],
[3, 9, 5]])
B = np.array([[3, 9, 5, 6],
[8, 7, 4, 2],
[4, 3, 0, 5]])
# Create a new, zero-filled, array C with length of A
C = np.zeros((A.shape[0], 4))
# Insert B at the beginning of C
C[:B.shape[0], :B.shape[1]] = B
print(C)
Out:
[[3, 9, 5, 6],
[8, 7, 4, 2],
[4, 3, 0, 5],
[0, 0, 0, 0],
[0, 0, 0, 0]]
# Using the numpy_indexed package reorder the rows.
# The last index of C is used as a fill value in case
# a row wasn't found in A thus filling the gaps with [0,0,0,0]
import numpy_indexed as npi
D = C[npi.indices(C[:, :-1], A, missing=-1)]
print(D)
Out:
[[8, 7, 4, 2],
[0, 0, 0, 0],
[4, 3, 0, 5],
[0, 0, 0, 0],
[3, 9, 5, 6]]