Python 使用pandas在单独的列中获取具有相同值组合的行

Python 使用pandas在单独的列中获取具有相同值组合的行,python,pandas,group-by,pandas-groupby,Python,Pandas,Group By,Pandas Groupby,我第一次尝试执行实体匹配,希望先“消除”明显的匹配,这样我就可以集中精力处理模糊的情况。我有一个包含近60万条关于衣服信息的数据集 我需要的是相同id、颜色和尺寸的供应商的所有不同价格 以下是一个例子: df = pd.DataFrame([{'product_id': 1, 'price': 10, 'supplier': 'A', 'color': "red", "size": "xl"},

我第一次尝试执行实体匹配,希望先“消除”明显的匹配,这样我就可以集中精力处理模糊的情况。我有一个包含近60万条关于衣服信息的数据集

我需要的是相同id、颜色和尺寸的供应商的所有不同价格

以下是一个例子:

df = pd.DataFrame([{'product_id': 1, 'price': 10, 'supplier': 'A', 'color': "red", "size": "xl"},
                       {'product_id': 2, 'price': 7, 'supplier': 'A', 'color': "blue", "size": "m"},
                       {'product_id': 2, 'price': 7, 'supplier': 'B', 'color': "blue", "size": "m"},
                       {'product_id': 1, 'price': 11, 'supplier': 'C', 'color': "red", "size": "xl"},
                       {'product_id': 3, 'price': 2, 'supplier': 'C', 'color': "red", "size": "s"},
                       {'product_id': 1, 'price': 3, 'supplier': 'A', 'color': "blue", "size": "XL"}]) #EDIT: added
这看起来像:

   product_id  price supplier color size
0           1     10        A   red   xl
1           2      7        A  blue    m
2           2      7        B  blue    m
3           1     11        C   red   xl
4           3      2        C   red    s
EDIT:
5           1      3        A  blue   xl
编辑备注:旧示例遗漏了一个关键方面:有些产品具有相同的产品id,但可以有多种颜色变化。设想产品1是一件standart白色T恤,我可以从多家供应商处订购不同尺寸和颜色的T恤。我还意识到我不需要供应商,见下文:

但我需要的是:

   product_id   color  size  price_a   price_b  price_c
0           1     red    xl    10        -        11
1           1    blue    xl     3        -        -
2           2    blue     m     7        7        -
3           3     red     s     -        -        2
我知道我必须根据“产品id”、“颜色”和“大小”以及聚合函数进行分组。但是我不知道怎样才能让熊猫创建新的栏目price_a、price_b和price_c

我觉得这应该很简单,但我不能让它工作。
非常感谢您的帮助

我的想法是两个连接两个数据帧-一个没有副本的数据帧和每种类型都有价格的数据帧。我相信这可以通过使用较少的行来实现,但我将为您提供我的解决方案,因为没有其他解决方案:

pd.concat([
    (
        df.drop_duplicates(subset=['product_id', 'color', 'size'], keep='first')
          .drop(columns='price')
          .reset_index(drop=True)
    )
    , 
    (
        df.groupby(['product_id', 'supplier'])['price']
          .apply(lambda x: list(x)[0])
          .to_frame()
          .unstack()
          .droplevel(0, axis=1)
          .reset_index()
          .drop('product_id', axis=1)
          .rename(columns={'A': 'price_a', 'B': 'price_b', 'C': 'price_c'})
     )
], 
    axis=1
).fillna('-')
输出:

    product_id  supplier    color   size    price_a  price_b    price_c
0            1         A      red     xl       10.0        -       11.0
1            2         A     blue      m        7.0      7.0          -
2            3         C      red      s          -        -        2.0

以下步骤像魔术一样实现了输出:

  • 使用
    groupby()
    将w.r.t
    product\u id
    color
    分组,并获取第一项颜色、大小以及价格和供应商的价值清单
  • 使用
    pd.Series.explode()
  • 使用
    DatFrame.Pivot()
    透视表<代码>产品id和
    颜色
    作为索引,
    供应商
    作为列,
    价格
    作为值
  • 使用
    pd.concat()
    将数据透视表与初始表合并,并使用
    DataFrame.drop()

  • 干杯,非常感谢你的回答!它适用于给定的示例。我意识到,我忘记了示例数据集中的一个重要示例(请参见问题中的上述编辑)。很遗憾,对于新条目,您的代码没有返回正确的结果。你知道如何解决这个问题吗?干杯,非常感谢你的回答!不幸的是,另一个答案也是如此……它适用于给定的示例。我意识到,我忘记了示例数据集中的一个重要示例(请参见问题中的上述编辑)。很遗憾,对于新条目,您的代码没有返回正确的结果。你知道怎么解决这个问题吗?我已经更新了答案。分组需要基于
    产品id
    颜色
    立即生效!非常感谢!(除了行“out.drop(columns=[“product_id”,“color”],inplace=True)”必须注释掉,因为out此时不存在。)感谢您的帮助!
    df = df.groupby(['product_id','color']).agg({'size':'first','price':list,'supplier':list}).reset_index()
    price_details = df.set_index(['product_id',"color","size"]).apply(pd.Series.explode).reset_index()
    price_details =pd.pivot_table(price_details,index=["product_id","color"], columns="supplier", values="price",aggfunc= 'first').add_prefix("price_").fillna("-").reset_index()
    out = pd.concat([df,price_details],axis=1)
    out.drop(columns = ["price"], inplace=True)
    out.supplier = out.supplier.apply(lambda x: x[0])
    print(out)
    
       product_id color size supplier  product_id color price_A price_B price_C
    0           1  blue   XL        A           1  blue       3       -       -
    1           1   red   xl        A           1   red      10       -      11
    2           2  blue    m        A           2  blue       7       7       -
    3           3   red    s        C           3   red       -       -       2