gpt4 book ai didi

python - 比较两个 Pandas 数据框的行?

转载 作者:太空狗 更新时间:2023-10-30 02:27:59 24 4
gpt4 key购买 nike

这是我的问题的延续。 Fastest way to compare rows of two pandas dataframes?

我有两个数据帧 AB:

A 是 1000 行 x 500 列,填充了指示存在或不存在的二进制值。

一个浓缩的例子:

    A   B   C   D   E  
0 0 0 0 1 0
1 1 1 1 1 0
2 1 0 0 1 1
3 0 1 1 1 0

B 是 1024 行 x 10 列,是从 0 到 1023 的二进制形式的完整迭代。

示例:

     0   1   2  
0 0 0 0
1 0 0 1
2 0 1 0
3 0 1 1
4 1 0 0
5 1 0 1
6 1 1 0
7 1 1 1

我试图在 A 的特定 10 列中找到 A 中的哪些行与 B 的每一行相对应。

A[My_Columns_List] 的每一行都保证在 B 中的某处,但并非 B 的每一行都与一个匹配A[My_Columns_List]

中的行

例如,我想显示对于 A 的列 [B,D,E]

A 的 [1,3] 行与 B[6] 行匹配,

A 的

[0] 行与 B[2] 行匹配,

A 的

[2] 行与 B[3] 行匹配。

我试过使用:

pd.merge(B.reset_index(), A.reset_index(),
left_on = B.columns.tolist(),
right_on =A.columns[My_Columns_List].tolist(),
suffixes = ('_B','_A')))

这行得通,但我希望这种方法会更快:

S = 2**np.arange(10)
A_ID = np.dot(A[My_Columns_List],S)
B_ID = np.dot(B,S)
out_row_idx = np.where(np.in1d(A_ID,B_ID))[0]

但是当我这样做时,out_row_idx 返回一个数组,其中包含 A 的所有索引,但它没有告诉我任何信息。我认为这种方法会更快,但我不知道为什么它会返回一个从 0 到 999 的数组。任何输入将不胜感激!

此外,这些方法归功于@jezrael 和@Divakar。

最佳答案

我会坚持我最初的回答,但也许解释得更好。

您要求比较 2 个 pandas 数据帧。因此,我将构建数据框。我可能会使用 numpy,但我的输入和输出将是数据帧。

设置

您说我们有一个 1000 x 500 的 1 和 0 数组。让我们构建它。

A_init = pd.DataFrame(np.random.binomial(1, .5, (1000, 500)))
A_init.columns = pd.MultiIndex.from_product([range(A_init.shape[1]/10), range(10)])
A = A_init

另外,我给了A一个MultiIndex轻松按 10 列分组。

解决方案

这与@Divakar 的回答非常相似,我将指出一个细微差别。

对于一组 10 个 1 和 0,我们可以将其视为长度为 8 的位数组。然后我们可以通过对 2 的幂数组进行点积来计算它的整数值。

twos = 2 ** np.arange(10)

我可以像这样一次对每组 10 个 1 和 0 执行此操作

AtB = A.stack(0).dot(twos).unstack()

stack为了更优雅地做点积,将一行 50 组 10 放入列中。然后我用unstack把它带回来了.

我现在有一个 1000 x 50 的数字数据框,范围从 0 到 1023。

假设B是一个数据框,每一行都是 1024 个 1 和 0 的唯一组合之一。 B应该排序为 B = B.sort_values().reset_index(drop=True) .

这是我认为我上次未能解释的部分。看看

AtB.loc[:2, :2]

enter image description here

(0, 0) 中的那个值位置,951表示 A 的第一行中的第一组 10 个 1 和 0匹配 B 中的行索引 951 .那正是你想要的!!!有趣的是,我从来没有看过 B。你知道为什么,B 是无关紧要的!!!这只是表示从 0 到 1023 的数字的一种愚蠢方式。这与我的答案不同,我忽略了 B。 .忽略这个无用的步骤应该可以节省时间。

这些都是采用两个数据帧的函数 AB并返回索引数据框,其中 A火柴B .剧透警报,我会忽略 B完全。

def FindAinB(A, B):
assert A.shape[1] % 10 == 0, 'Number of columns in A is not a multiple of 10'
rng = np.arange(A.shape[1])
A.columns = pd.MultiIndex.from_product([range(A.shape[1]/10), range(10)])

twos = 2 ** np.arange(10)

return A.stack(0).dot(twos).unstack()

def FindAinB2(A, B):
assert A.shape[1] % 10 == 0, 'Number of columns in A is not a multiple of 10'
rng = np.arange(A.shape[1])
A.columns = pd.MultiIndex.from_product([range(A.shape[1]/10), range(10)])
# use clever bit shifting instead of dot product with powers
# questionable improvement
return (A.stack(0) << np.arange(10)).sum(1).unstack()

我正在引导我内心的@Divakar(阅读,这是我从 Divakar 那里学到的东西)

def FindAinB3(A, B):
assert A.shape[1] % 10 == 0, 'Number of columns in A is not a multiple of 10'
a = A.values.reshape(-1, 10)
a = np.einsum('ij->i', a << np.arange(10))
return pd.DataFrame(a.reshape(A.shape[0], -1), A.index)

极简主义单线

f = lambda A: pd.DataFrame(np.einsum('ij->i', A.values.reshape(-1, 10) << np.arange(10)).reshape(A.shape[0], -1), A.index)

像这样使用它

f(A)

时机

FindAinB3 快了一个数量级

enter image description here

关于python - 比较两个 Pandas 数据框的行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38493795/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com