Pandas: 如何以两种方式获取两列值的唯一组合?

Pandas: How to get Unique combinations of two column values in either ways?

我想知道如果值是相似的组合,我们如何才能得到两个列值的唯一组合。下面是数据框

我尝试使用以下代码,但我的预期输出不同

df.groupby(['column1', 'column2'], as_index = 假).agg({'expense' : 'sum'})

这是 的变体,但一个重要的区别是您似乎并不关心 column1column2 的顺序。在我分享解决方案之前,这是伪代码:

  1. 创建一个 id 列,我们可以使用它来查找 column1column2 的集合相同的行
  2. 将链接 post 中的方法应用到 id
  3. 根据 id 删除重复项

这是我对数据的手动转录。以后请以文本形式提供示例数据,而不是屏幕截图。

column1,column2,salary
ram,shyam,100
sita,geeta,500
geeta,sita,300
shyam,ram,600
sohan,mohan,200
mohan,sohan,400

这是代码

>>> import pandas as pd
>>> df = pd.read_csv('data.csv')
>>> hash_func = lambda n: hash("-".join(sorted(n)))
>>> df['id'] = df[['column1','column2']].apply(hash_func, axis=1)
>>> df
  column1 column2  salary                   id
0     ram   shyam     100 -1387604912582040812
1    sita   geeta     500  9030593041392264307
2   geeta    sita     300  9030593041392264307
3   shyam     ram     600 -1387604912582040812
4   sohan   mohan     200  6327789560655124249
5   mohan   sohan     400  6327789560655124249
>>> df['expense'] = df.groupby('id')['salary'].transform('sum')
>>> df
   column1 column2  salary                   id  expense
0     ram   shyam     100  7227562739062788100      700
1    sita   geeta     500  6328366926112663723      800
2   geeta    sita     300  6328366926112663723      800
3   shyam     ram     600  7227562739062788100      700
4   sohan   mohan     200 -3239226935758438599      600
5   mohan   sohan     400 -3239226935758438599      600
>>> df = df.drop_duplicates(subset=['id'])
>>> df
  column1 column2  salary                   id  expense
0     ram   shyam     100  7227562739062788100      700
1    sita   geeta     500  6328366926112663723      800
4   sohan   mohan     200 -3239226935758438599      600
>>> df = df.drop(columns=['id','salary']) # some extra cleanup
>>> df 
  column1 column2  expense
0     ram   shyam      700
1    sita   geeta      800
4   sohan   mohan      600

我遵循了这些步骤

df['pairs'] = df['col1'] + '-' + df['col2']

然后将 foo 函数应用于此列 这个函数的想法是获取 pairs 列数据并根据对中每个元素的第一个字符对其进行排序。

例如输入是 ram-shyamram-shaym 我们将得到输出 ram-shyam

这是foo函数-

def foo(s):
    lst_s = s.split('-')
    temp = {}
    for idx, name in enumerate(lst_s):
        temp[idx]= name[0]

    temp = dict(sorted(temp.items(), key=lambda item: item[1]))
    
    final = []
    for key in temp.keys():
        final.append(lst_s[key])
    return '-'.join(final)

现在在 pairs 列上应用此函数

df['unique-pair'] = df['pairs'].apply(foo)

输出现在看起来像这样 -

col1    col2    salary  unique-pair     pairs
0   ram     shyam   100     ram-shyam   ram-shyam
1   sita    gita    500     gita-sita   sita-gita
2   gita    sita    300     gita-sita   gita-sita
3   shyam   ram     600     ram-shyam   shyam-ram
4   sohan   mohan   200     mohan-sohan     sohan-mohan
5   mohan   sohan   400     mohan-sohan     mohan-sohan

现在您可以按

分组
df.groupby(['unique-pair']).agg({'salary':sum})

最终输出为-

salary
unique-pair     
gita-sita   800
mohan-sohan     600
ram-shyam   700

您可以对第一列和第二列进行排序,以便 a,bb,a 在 groupby 中被视为相同。

现在,由于 sort() 已弃用,我们可以使用 numpy 排序和 re-create 新数据框。

假设以下 csv_file

 column1,column2,salary
    a,b,1
    c,b,3
    b,a,10
    b,c,30
    d,e,99

我们可以这样做:

import pandas as pd
import numpy as np

df = pd.read_csv("csvfile.csv",)
print("Original:\n ",df.head())

print ("\nGrouped sum:\n")
print ((pd.concat([pd.DataFrame(np.sort(df[df.columns[:2]], axis=1), columns=df.columns[:2]),\
                   df["salary"]], axis=1)).reset_index(drop=True, inplace=False).groupby\
                   (["column1", "column2"]).sum())

输出如下图:

Original:
    column1 column2  salary
0       a       b       1
1       c       b       3
2       b       a      10
3       b       c      30
4       d       e      99

Grouped sum:

                 salary
column1 column2        
a       b            11
b       c            33
d       e            99