【问题标题】:Concatenate two csv files based on column content in Pandas根据 Pandas 中的列内容连接两个 csv 文件
【发布时间】:2023-04-08 05:52:01
【问题描述】:

我有两个带有示例数据的大型 CSV 文件,如下所示:

df1 = 
Index    Fruit   Vegetable    
    0    Mango   Spinach
    1    Berry   Carrot
    2    Banana  Cabbage   
df2 = 
Index   Unit        Price
   0    Mango       30
   1    Artichoke   45
   2    Banana      12
   3    Berry       10
   4    Cabbage     25
   5    Rice        40
   6    Spinach     34
   7    Carrot      08
   8    Lentil      12
   9    Pot         32

我想创建以下数据框:

df3 = 
Index    Fruit   Price      Vegetable    Price   
    0    Mango   30         Spinach      34
    1    Berry   10         Carrot       08   
    2    Banana  12         Cabbage      25

我希望在 df1 中逐行比较每个单位的价格。如果价格在 5 美元以内,我想将它们输出到单独的数据框中,如下所示:

df4 = 
Index    Fruit   Price      Vegetable    Price   
    0    Mango   30         Spinach      34
    1    Berry   10         Carrot       08 

实现这一目标的通用方法是什么?提前谢谢你。

【问题讨论】:

  • 我建议在这里使用两个joins 将来自 df2 的价格信息与 df1 结合起来。

标签: python pandas dataframe merge


【解决方案1】:

您可以使用replace 基于df2 创建价格数据框,然后使用join 与原始数据连接。

请注意,不鼓励重复的列名:

# print to see what it does
item_prices = dict(zip(df2.Unit, df2.Price))

out = df1.join(df1.replace(item_prices).add_suffix('_Price')).sort_index(axis=1)

输出:

        Fruit  Fruit_Price Vegetable  Vegetable_Price
Index                                                
0       Mango           30   Spinach               34
1       Berry           10    Carrot                8
2      Banana           12   Cabbage               25

对于下一个问题,您需要一个布尔 loc 访问权限:

out[abs(out['Fruit_Price'] - out['Vegetable_Price']) < 5]

query:

out.query('abs(Fruit_Price-Vegetable_Price)<5')

输出:

       Fruit  Fruit_Price Vegetable  Vegetable_Price
Index                                               
0      Mango           30   Spinach               34
1      Berry           10    Carrot                8

【讨论】:

  • 如果 df2 中的单位名称是 Mango_123、Spinach_435 等,对代码的修改是什么。我相信在加入之前应该与 df1 进行字符串匹配,但不知道该怎么做。
【解决方案2】:

您可以使用双重合并:

fruit = df1[['Fruit']].merge(df2.rename(columns={'Unit': 'Fruit'}), on='Fruit')
veggie = df1[['Vegetable']].merge(df2.rename(columns={'Unit': 'Vegetable'}), on='Vegetable')

df3 = pd.concat([fruit, veggie], axis=1)
print(df3)

# Output:
    Fruit  Price Vegetable  Price
0   Mango     30   Spinach     34
1   Berry     10    Carrot      8
2  Banana     12   Cabbage     25

然后

df4 = df3[np.abs(np.subtract(*out['Price'].values.T)) <= 5]
print(df4)

# Output:
   Fruit  Price Vegetable  Price
0  Mango     30   Spinach     34
1  Berry     10    Carrot      8

【讨论】:

  • 谢谢,这也有效。但是,我在上面的答案中也发布了一个问题-如果 df2 中的单位名称是 Mango_123、Spinach_435 等,对代码的修改是什么。我相信在加入之前应该与 df1 进行字符串匹配但不确定怎么做。
【解决方案3】:

一种通用的替代方法(可以处理任意数量的类别)是在之前(使用melt)和之后(使用pivot)重塑。这样做的好处是可以创建一个非常方便明确识别价格类别的 MultiIndex:

out = (df1.melt(id_vars='Index', value_name='Unit')
          .merge(df2.drop(columns='Index'), on='Unit')
          .pivot(index='Index', columns='variable', values=['Unit', 'Price'])
       )

输出:

            Unit           Price          
variable   Fruit Vegetable Fruit Vegetable
Index                                     
0          Mango   Spinach    30        34
1          Berry    Carrot    10         8
2         Banana   Cabbage    12        25
对 diff ≤ 5 的行进行子集化:
out[out['Price'].diff(axis=1).abs().le(5).any(1)]

输出:

           Unit           Price          
variable  Fruit Vegetable Fruit Vegetable
Index                                    
0         Mango   Spinach    30        34
1         Berry    Carrot    10         8

【讨论】:

    猜你喜欢
    • 2016-09-13
    • 1970-01-01
    • 1970-01-01
    • 2016-08-12
    • 2015-01-18
    • 1970-01-01
    • 2021-11-06
    • 1970-01-01
    • 2015-04-22
    相关资源
    最近更新 更多