Pandas合并Dataframes

时间:2017-03-15 19:45:13

标签: python pandas join dataframe merge

我希望将一组数据与该数据的累计汇总进行比较。

在下面的示例中,我想知道每家餐厅的价格与所有餐厅的总数相比多少钱。我想知道这一天。如果一家餐馆当天关闭,我仍然想要在总帐单栏中返回当天的名称和餐馆名称,其中NaN(或零)。

(我知道还有其他方法可以做到这一点,但请考虑这是一个关于合并的问题,因为有一个原因需要使用两个不同的数据帧)

所以,我想要的输出是:

day   total_bill_x   restaurant   total_bill_y

Fri        651.76   DINER A     325.88 
Sat      3,556.80   DINER A   1,778.40 
Sun      1,627.16   DINER A        NaN 
Thur     2,192.66   DINER A   1,096.33 

但是由于外连接的工作性质,我能得到的最远的东西会返回类似下面的内容:

day   total_bill_x   restaurant   total_bill_y

Fri        651.76   DINER A   325.88 
Sat      3,556.80   DINER A   1,778.40 
Sun      1,627.16   NaN        NaN 
Thur     2,192.66   DINER A   1,096.33 

问题在于我没有想到可以支持这类输出的合并 - 如果没有匹配,DINER A就会消失。

我的真实数据集会变得更糟,这些数据集将由数十家餐馆组成。

是否可以进行外连接,如果不匹配,将从正在连接的表中获取字段?如何查看较大表中的所有记录,以查找较小表中没有匹配的记录?

我认为这是一个有趣的问题,并且肯定对其他人如何处理感兴趣..谢谢!

示例代码遵循:

import pandas as pd
df=pd.read_csv("https://raw.githubusercontent.com/wesm/pydata-book/master/ch08/tips.csv", sep=',')
df2=pd.read_csv("https://raw.githubusercontent.com/wesm/pydata-book/master/ch08/tips.csv", sep=',')

df=df[df['day']!="Sun"]
df['restaurant']="DINER A"
df3=df.append(df2)
df_output=df.groupby(['restaurant','day'])[['total_bill']].sum().reset_index()
df_output2=df3.groupby(['day'])[['total_bill']].sum().reset_index()

pd.merge(df_output2,df_output, on='day', how="outer")

2 个答案:

答案 0 :(得分:1)

您可以分两步完成此操作。首先将餐馆A的总账单值映射到df_output2

df_output2['DINER_A'] = df_output2['day'].map(df_output.set_index('day')['total_bill'])

给你

    day     total_bill  DINER_A
0   Fri     651.76      325.88
1   Sat     3556.80     1778.40
2   Sun     1627.16     NaN
3   Thur    2192.66     1096.33

现在融化DINER_A列以创建两列restaurant和total_bill

df_output2 = pd.melt(df_output2, id_vars=['day', 'total_bill'],var_name="restaurant", value_name="total_bill_A")

你得到了

    day    total_bill   restaurant  total_bill_A
0   Fri    651.76       DINER_A     325.88
1   Sat    3556.80      DINER_A     1778.40
2   Sun    1627.16      DINER_A     NaN
3   Thur   2192.66      DINER_A     1096.33

答案 1 :(得分:1)

设置

df = pd.read_csv(
    "https://raw.githubusercontent.com/wesm/pydata-book/master/ch08/tips.csv", sep=',')

d1 = pd.concat([df.query('day != "Sun"'), df], keys=['DINER A', 'DINER B']) \
    .rename_axis(['restaurant', None]).reset_index('restaurant')

建立一个包含所有餐馆和日期的pd.MultiIndex

mux = pd.MultiIndex.from_product([
        d1.restaurant.unique(),
        d1.day.unique()
    ], names=['restaurant', 'day'])

执行groupby + join + reindex

d2 = d1.groupby(['day']).total_bill.sum()
d3 = d1.groupby(['restaurant', 'day'])[['total_bill']].sum()

d3.reindex(mux).join(d2, lsuffix='_x', rsuffix='_y').reset_index()

  restaurant   day  total_bill_x  total_bill_y
0    DINER A   Sat       1778.40       3556.80
1    DINER A  Thur       1096.33       2192.66
2    DINER A   Fri        325.88        651.76
3    DINER A   Sun           NaN       1627.16
4    DINER B   Sat       1778.40       3556.80
5    DINER B  Thur       1096.33       2192.66
6    DINER B   Fri        325.88        651.76
7    DINER B   Sun       1627.16       1627.16