这是我的问题的继续。比较两个熊猫数据帧的行的最快方法?
我有两个数据框A
和B
:
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]
例如,我想表明,列[B,D,E]
的A
,
行[1,3]
A的匹配与行[6]
的B
,
排[0]
A的匹配了行[2]
的B
,
排[2]
A的匹配了行[3]
的B
。
我试过使用:
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]
该(0, 0)
位置中的值951
表示第一行中的10和1的第一组与索引A
中的行匹配。那就是你想要的!!!有趣的是,我从没看过B。你知道为什么,B不相关!!!这只是代表从0到1023的数字的愚蠢方式。这与我的答案有所不同,我忽略了。忽略这一无用的步骤应该可以节省时间。B
951
B
这些都是需要两个dataframes的所有功能A
,并B
和回报指数,其中的数据帧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快一个数量级
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句