【问题标题】:How to do pandas equivalence of SQL outer join without a key如何在没有键的情况下进行 SQL 外连接的 pandas 等价
【发布时间】:2017-10-27 08:52:12
【问题描述】:

在 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 合并?

【问题讨论】:

  • 在我看来,您可能正在尝试做一个cross join?在 Python 中,这可以通过 vals=[(x,y) for x in list1 for y in list2] non-Pandasically 来完成
  • 我有一个版本的代码根本不使用数据帧。它使用数据作为列表,并使用循环和列表推导来解决它。然后我对如果我在数据帧上使用 SQL 之类的连接来生成数据并将结果作为数据帧输出会怎样?到目前为止,根据这里的帖子来解决答案,现在看起来很有希望。但是你的评论是一个有用的代码,可以不同地给猫换皮(产生嵌套列表输出)。感谢分享。
  • 我还不知道 Python 中通过 pandas 的 cross join 功能,但会密切关注线程!
  • 交叉连接可能是一个不同但相关的概念。看看我在这里接受的答案。它解决了我问的实际问题。谢谢你的评论。我只是基于它建模了一些东西来解决我正在处理的代码的另一部分。 :-)

标签: python join dataframe merge


【解决方案1】:

我确信有比下面的 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        *

【讨论】:

    【解决方案2】:

    您可以向两个 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
    

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

    【讨论】:

      【解决方案3】:

      在@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
      

      【讨论】:

        【解决方案4】:

        cross-joinintroduced in Pandas 1.2.0 可以做到这一点。只需运行:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-10-09
          • 1970-01-01
          • 1970-01-01
          • 2013-05-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多