笛卡尔的笛卡尔产品

我有两个pandas数据框:

from pandas import DataFrame df1 = DataFrame({'col1':[1,2],'col2':[3,4]}) df2 = DataFrame({'col3':[5,6]}) 

获得笛卡尔产品的最佳做法是什么(当然,没有像我这样明确地写出)?

 #df1, df2 cartesian product df_cartesian = DataFrame({'col1':[1,2,1,2],'col2':[3,4,3,4],'col3':[5,5,6,6]}) 

如果你有一个重复的每一行的关键,那么你可以使用合并产生笛卡尔产品(就像你在SQL中)。

 from pandas import DataFrame, merge df1 = DataFrame({'key':[1,1], 'col1':[1,2],'col2':[3,4]}) df2 = DataFrame({'key':[1,1], 'col3':[5,6]}) merge(df1, df2,on='key')[['col1', 'col2', 'col3']] 

看到这里的文件: http : //pandas.pydata.org/pandas-docs/stable/merging.html#brief-primer-on-merge-methods-relational-algebra

这不会赢得代码高尔夫比赛,并从以前的答案中借鉴 – 但清楚地表明如何添encryption钥,以及如何join工作。 这将从列表创build2个新的dataframe,然后添encryption钥来执行笛卡尔积。

我的用例是,我需要列表中每周的所有商店ID列表。 所以,我创build了我想要的所有星期的清单,然后列出了我想映射它们的所有商店ID。

我select的合并离开了,但是在语义上和这个设置的内部是一样的。 你可以在关于合并的文档中看到这一点,如果在两个表中键组合多次出现,那么它将执行笛卡尔乘积 – 这就是我们所设置的。

 days = pd.DataFrame({'date':list_of_days}) stores = pd.DataFrame({'store_id':list_of_stores}) stores['key'] = 0 days['key'] = 0 days_and_stores = days.merge(stores, how='left', on = 'key') days_and_stores.drop('key',1, inplace=True) 

作为替代,可以依赖itertools提供的笛卡尔产品: itertools.product ,它避免了创build临时密钥或修改索引:

 import numpy as np import pandas as pd import itertools def cartesian(df1, df2): rows = itertools.product(df1.iterrows(), df2.iterrows()) df = pd.DataFrame(left.append(right) for (_, left), (_, right) in rows) return df.reset_index(drop=True) 

快速testing:

 In [46]: a = pd.DataFrame(np.random.rand(5, 3), columns=["a", "b", "c"]) In [47]: b = pd.DataFrame(np.random.rand(5, 3), columns=["d", "e", "f"]) In [48]: cartesian(a,b) Out[48]: abcdef 0 0.436480 0.068491 0.260292 0.991311 0.064167 0.715142 1 0.436480 0.068491 0.260292 0.101777 0.840464 0.760616 2 0.436480 0.068491 0.260292 0.655391 0.289537 0.391893 3 0.436480 0.068491 0.260292 0.383729 0.061811 0.773627 4 0.436480 0.068491 0.260292 0.575711 0.995151 0.804567 5 0.469578 0.052932 0.633394 0.991311 0.064167 0.715142 6 0.469578 0.052932 0.633394 0.101777 0.840464 0.760616 7 0.469578 0.052932 0.633394 0.655391 0.289537 0.391893 8 0.469578 0.052932 0.633394 0.383729 0.061811 0.773627 9 0.469578 0.052932 0.633394 0.575711 0.995151 0.804567 10 0.466813 0.224062 0.218994 0.991311 0.064167 0.715142 11 0.466813 0.224062 0.218994 0.101777 0.840464 0.760616 12 0.466813 0.224062 0.218994 0.655391 0.289537 0.391893 13 0.466813 0.224062 0.218994 0.383729 0.061811 0.773627 14 0.466813 0.224062 0.218994 0.575711 0.995151 0.804567 15 0.831365 0.273890 0.130410 0.991311 0.064167 0.715142 16 0.831365 0.273890 0.130410 0.101777 0.840464 0.760616 17 0.831365 0.273890 0.130410 0.655391 0.289537 0.391893 18 0.831365 0.273890 0.130410 0.383729 0.061811 0.773627 19 0.831365 0.273890 0.130410 0.575711 0.995151 0.804567 20 0.447640 0.848283 0.627224 0.991311 0.064167 0.715142 21 0.447640 0.848283 0.627224 0.101777 0.840464 0.760616 22 0.447640 0.848283 0.627224 0.655391 0.289537 0.391893 23 0.447640 0.848283 0.627224 0.383729 0.061811 0.773627 24 0.447640 0.848283 0.627224 0.575711 0.995151 0.804567 

如果没有重叠的列,不想添加一个,并且可以丢弃dataframe的索引,这可能更容易:

 df1.index[:] = df2.index[:] = 0 df_cartesian = df1.join(df2, how='outer') df_cartesian.index[:] = range(len(df_cartesian)) 

这个最小的代码需要。 创build一个共同的“关键”笛卡尔合并两个:

 df1['key'] = 0 df2['key'] = 0 df_cartesian = df1.merge(df2, how='outer') 

我发现使用pandasMultiIndex是最好的工具。 如果列表列表lists_list ,请调用pd.MultiIndex.from_product(lists_list)并遍历结果(或在DataFrame索引中使用它)。

使用pd.MultiIndex.from_product作为其他空数据pd.MultiIndex.from_product的索引,然后重置其索引,即可完成。

 a = [1, 2, 3] b = ["a", "b", "c"] index = pd.MultiIndex.from_product([a, b], names = ["a", "b"]) pd.DataFrame(index = index).reset_index() 

出:

  ab 0 1 a 1 1 b 2 1 c 3 2 a 4 2 b 5 2 c 6 3 a 7 3 b 8 3 c