如何在没有键的情况下做SQL外连接的pandas等价

时间:2017-05-26 12:43:07

标签: python join dataframe merge

在SQL中,您可以在没有键的情况下连接两个表,以便两个表的所有记录相互合并。如果支持pandas.concat()pandas.merge()或其他一些pandas语法,它可以帮助我解决我想要解决的问题的一个步骤。我在帮助文档中找到了一个外连接选项,但是我找不到一个确切的语法来执行我想要的操作(加入所有没有键的记录)。

更好地解释一下:

import pandas as pd

lunchmenupairs2 = [["pizza", "italian"],["lasagna", "italian"],["orange", "fruit"]]
teamcuisinepreferences2 = [["ian", "*"]]

lunchLabels = ["Food", "Type"]
teamLabels = ["Person", "Type"]

df1 = pd.DataFrame.from_records(lunchmenupairs2, columns=lunchLabels)
df2 = pd.DataFrame.from_records(teamcuisinepreferences2, columns=teamLabels)

print(df1)
print(df2)

输出这些表格:

      Food     Type
0    pizza  italian
1  lasagna  italian
2   orange    fruit

  Person     Type
0    ian        *

我希望合并的最终结果是:

  Person     Type Food     Type
0  ian        *   pizza     italian
1  ian        *   lasagna   italian
2  ian        *   orange    fruit

然后我可以轻松删除我不想要的列,并转到我正在处理的代码中的下一步。这不起作用:

merged_data = pd.merge(left=df2,right=df1, how='outer')

有没有办法进行此类DataFrame合并?

4 个答案:

答案 0 :(得分:4)

您可以使用常量值

向两个dfs添加列
>>>df1['joincol'] = 1
>>>df2['joincol'] = 1
>>>pd.merge(left=df2,right=df1, on='joincol', how='outer')
  Person Type_x  joincol     Food   Type_y
0    ian      *        1    pizza  italian
1    ian      *        1  lasagna  italian
2    ian      *        1   orange    fruit

然后在删除其他不需要的列时将其删除。

答案 1 :(得分:1)

这可以通过 cross-joinintroduced in Pandas 1.2.0 实现。只需运行:

df1.merge(df2, how='cross')

答案 2 :(得分:0)

我确信有一种比下面while方法更好的方法,但这应该可以解决问题:

df2_copy = df2.copy(deep=True)

# Basically repeat the same row in df2 until the lengths of the two dataframes are equal
while df2.shape[0] < df1.shape[0]:
    df2 = df2.append(df2_copy)

# Join on the indices of each dataframe ([0,1,2] to [0,1,2])
together = df1.join(df2, lsuffix='_df1', rsuffix='_df2').drop_duplicates()

# Fill 'ian' down
together['Person'] = together['Person'].ffill(axis=0)

# Fill type2 down
together['Type_df2'] = together['Type_df2'].ffill(axis=0)

together现在是:

      Food Type_df1 Person Type_df2
0    pizza  italian    ian        *
1  lasagna  italian    ian        *
2   orange    fruit    ian        *

答案 3 :(得分:0)

在@EFT答案的基础上,我经常需要一些值和日期的组合,以下为解决方案。可以很容易地概括。

df1=pd.DataFrame({'ticker':['a','b']})
df2=pd.DataFrame({'date':pd.date_range('2010-01-01','2010-03-01',freq='1M')})
pd.DataFrame({'ticker':df1['ticker'].unique(),'key':np.nan}).merge(pd.DataFrame({'date':df2['date'].unique(),'key':np.nan}),on='key').drop('key',1)

  ticker       date
0      a 2010-01-31
1      a 2010-02-28
2      b 2010-01-31
3      b 2010-02-28