使用Pandas,希望按最小值/最大值的多列分组,并向最小值/最大值列添加另一个列值

bfhwhh0e  于 2022-12-16  发布在  其他
关注(0)|答案(2)|浏览(219)

首先,如果标题很难理解,我很抱歉。
目标:我尝试按source, type列分组,按结果为每个组添加min,max列,然后将相关的target列添加到minmax列(在值前面)。
我不知道如何获得这种格式的Pandas结果:
| 源|类型|最小值|最大值|
| - ------|- ------|- ------|- ------|
| 人员1|弓|第二个人:0.001|第三个人:0.05|
我有一个字典清单如下:

`[{'source': 'Person1', 'target': 'Person2', 'type': 'bow', 'similarity': 0.636}, {'source': 'Person1', 'target': 'Person2', 'type': 'bigram', 'similarity': 0.040}, {'source': 'Person1', 'target': 'Person2', 'type': 'tfidf', 'similarity': 0.433}, {'source': 'Person1', 'target': 'Person3', 'type': 'bow', 'similarity': 0.699}, {'source': 'Person1', 'target': 'Person3', 'type': 'bigram', 'similarity': 0.171}, {'source': 'Person1', 'target': 'Person3', 'type': 'tfidf', 'similarity': 0.522}]`

在该表中,如下所示:
| 源|靶|类型|相似性|
| - ------|- ------|- ------|- ------|
| 人员1|人员2|弓|0.636|
| 人员1|人员2|双字母组|0.040|
| 人员1|人员2|特菲德夫|0.433|
| 人员1|人员3|弓|0.699|
| 人员1|人员3|双字母组|零点一七一|
| 人员1|人员3|特菲德夫|零点五二二|
对于group by,min/max,我使用以下公式:

df = df.groupby(['source','type']).similarity.agg(['min','max'])

其结果是:
| 源|类型|最小值|最大值|
| - ------|- ------|- ------|- ------|
| 人员1|弓|0.636| 0.699|
| 人员1|双字母组|0.040|零点一七一|
| 人员1|特菲德夫|0.433|零点五二二|
到目前为止一切都很好,但我如何将输出转换为以下结构:

[资料来源]:资料来源;[类型]:类型;[min]:目标值:min(相似性);[最大值]:目标值:最大值(相似度)

| 源|类型|最小值|最大值|
| - ------|- ------|- ------|- ----------------------------------------------------|
| 人员1|弓|受试者2:0.636|受试者3:0.699|
| 人员1|双字母组|受试者2:0.040|受试者3:0.171|
| 人员1|特菲德夫|受试者3:0.433|受试者3:0.522|
我是否应该使用.loc来查找最小值/最大值所在的行,然后以某种方式将这些值添加到结果中?

jecbmhm3

jecbmhm31#

下面是使用GroupBypandas.merge的方法:

g = df.groupby(by=['source', 'type'], sort=False)
​​
out = (
            pd.merge(df.loc[g['similarity'].idxmin()]
                       .rename(columns= {'similarity': 'sim_min', 'target': 'target_min'}),
                     df.loc[g['similarity'].idxmax()]
                       .rename(columns= {'similarity': 'sim_max', 'target': 'target_max'}),
                     on=['source','type'])
              .assign(min=lambda x: x.pop('target_min') + ': ' + x.pop('sim_min').astype(str),
                      max=lambda x: x.pop('target_max') + ': ' + x.pop('sim_max').astype(str))
        )

另一种变体:

g = df.groupby(by=['source', 'type'], sort=False)
​
​
out = (
            pd.merge(df.loc[g['similarity'].idxmin()]
                         .assign(min= lambda x: x[['target', 'similarity']]
                                                     .astype(str).agg(": ".join, axis=1)),
                     df.loc[g['similarity'].idxmax()]
                         .assign(max= lambda x: x[['target', 'similarity']]
                                                     .astype(str).agg(": ".join, axis=1)),
                     on=['source','type'], suffixes=('', '_'))
                .loc[:, ['source', 'type', 'min', 'max']]
      )
#输出:
print(out)

    source    type             min             max
0  Person1     bow  Person2: 0.636  Person3: 0.699
1  Person1  bigram   Person2: 0.04  Person3: 0.171
2  Person1   tfidf  Person2: 0.433  Person3: 0.522
zdwk9cvp

zdwk9cvp2#

示例

data = [['Person1', 'Person2', 'bow', 0.636],
        ['Person1', 'Person2', 'bigram', 0.04],
        ['Person1', 'Person2', 'tfidf', 0.433],
        ['Person1', 'Person3', 'bow', 0.699],
        ['Person1', 'Person3', 'bigram', 0.171],
        ['Person1', 'Person3', 'tfidf', 0.522]]
df = pd.DataFrame(data, columns=['source', 'target', 'type', 'similarity'])

df

source  target  type    similarity
0   Person1 Person2 bow     0.6
1   Person1 Person2 bigram  0.0
2   Person1 Person2 tfidf   0.4
3   Person1 Person3 bow     0.7
4   Person1 Person3 bigram  0.2
5   Person1 Person3 tfidf   0.5

进程

df.groupby(['source','type']).agg([min, max])

结果:

target              similarity
                min     max         min     max
source  type                
Person1 bigram  Person2 Person3     0.0     0.2
        bow     Person2 Person3     0.6     0.7
        tfidf   Person2 Person3     0.4     0.5

使结果到你想要的输出
:加到df的目标列的值上,将result的值改为str,然后将它们组合起来。

完整代码和输出

(df.assign(target=df['target'] + ': ')
 .groupby(['source','type']).agg([min, max]).astype('str')
 .groupby(level=1, axis=1, sort=False).sum().reset_index())

输出:

source  type    min             max
0   Person1 bigram  Person2: 0.04   Person3: 0.171
1   Person1 bow     Person2: 0.636  Person3: 0.699
2   Person1 tfidf   Person2: 0.433  Person3: 0.522

相关问题