【问题标题】:How to add tricky 1-to-1 : M-to-M relations for a dataframe in a new column while grouping data如何添加棘手的 1 对 1:分组数据时新列中数据帧的 M 对 M 关系
【发布时间】:2021-10-10 15:41:02
【问题描述】:

我有以下示例数据框

In [1]: df = pd.DataFrame({'Name': {0: 'ahmed',
  1: 'ahmed',
  2: 'mohamed',
  3: 'mohamed',
  4: 'hassan',
  5: 'ali',
  6: 'nice',
  7: 'bad'},
 'Location': {0: 'A', 1: 'A', 2: 'B', 3: 'B', 4: 'C', 5: 'C', 6: 'D', 7: 'D'},
 'Prof': {0: 'doc',
  1: 'doc',
  2: 'eng',
  3: 'doc',
  4: 'eng',
  5: 'eng',
  6: 'doc',
  7: 'eng'}})

In [2]: df
Out[2]:
      Name Location Prof
0    ahmed        A  doc
1    ahmed        A  doc
2  mohamed        B  eng
3  mohamed        B  doc
4   hassan        C  eng
5      ali        C  eng
6     nice        D  doc
7      bad        D  eng

我想添加一个新列Relations,其中将包含职业与姓名和位置组合

我想要这个

In [3]: df
Out[3]:
      Name Location      Prof relation
0    ahmed        A       doc   1_to_1
1  mohamed        B  eng, doc   1_to_M
2   hassan        C       eng   M_to_1
3      ali        C       eng   M_to_1
4     nice        D       doc   M_to_M
5      bad        D       eng   M_to_M

除了Relations 列,我只想要['Prof'] 中的唯一值;

df.groupby(['Name', 'Location'])['Prof'].agg(','.join)

使用上面的代码行导致doc,doc 用于第一条记录,这是我不想要的,我之前无法删除重复项,因为我在原始数据中有许多其他列构成第一行不重复。

【问题讨论】:

  • 看看您是否需要从下面的答案中进一步澄清。如果没有更多问题,请接受您选择的答案,让我们知道最适合您需求的任何答案。还请考虑支持对您有帮助的答案(包括您接受的答案)。谢谢!
  • 有什么更新吗?如果需要任何澄清,请告诉我们。谢谢!

标签: python pandas dataframe pandas-groupby


【解决方案1】:

您可以在 groupby 之后的 lambda 中使用 set,如下所示,然后您可以使用合并两个 DataFrame 并获得您想要的内容,如下所示:

>>> relation_list = []
>>> for col in ['Name', 'Prof']:
...    relation_list.append(dict(df.groupby('Location')[col].apply(lambda x : '1' if len(set(x))==1 else 'M')))

>>> df_rel = pd.DataFrame(relation_list).apply(lambda x : '_to_'.join(x)).to_frame().reset_index().rename({'index': 'Location'}, axis=1)
>>> df_rel
    Location    0
0   A           1_to_1
1   B           1_to_M
2   C           M_to_1
3   D           M_to_M

>>> df_prof = df.groupby(['Name', 'Location'])['Prof'].apply(lambda x : ','.join(set(x))).to_frame().reset_index()
>>> df_prof

     Name    Location   Prof
0   ahmed    A          doc
1   ali      C          eng
2   bad      D          eng
3   hassan   C          eng
4   mohamed  B          eng,doc
5   nice     D          doc


>>> df_final = df_prof.merge(df_rel, on='Location').rename({0: 'relation'}, axis=1)
>>> df_final.sort_values('Location')
    Name        Location    Prof      relation
0   ahmed       A           doc       1_to_1
5   mohamed     B           eng,doc   1_to_M
1   ali         C           eng       M_to_1
2   hassan      C           eng       M_to_1
3   bad         D           eng       M_to_M
4   nice        D           doc       M_to_M

【讨论】:

  • 谢谢,对“教授”部分的帮助。对于关系部分,我需要任何给定“位置”中的“教授”和“姓名”之间的关系。对于 Location=A,只有 Ahmed 和 doc,一对一。位置 = B,Mohamed 和两位教授(doc 和 eng),所以 1 到 M。 Location=C,两个名字(hassan & ali)和一个 Prof eng,所以 M-to-1。 Location=D 两个名字和两个教授,所以 M 到 M
  • @Nagib 已编辑答案
【解决方案2】:

第一步:您可以为Location设置relation,如下:

通过.groupby()nunique() 获取每个LocationNameProf 的唯一计数。

使用np.select() 设置relation

# Get the unique counts of `Name` and `Prof` for each `Location`
df_count = df.groupby('Location', as_index=False)[['Name', 'Prof']].nunique()

# Set up `relation` using `np.select()`
cond_list = [(df_count['Name'] == 1) & (df_count['Prof'] == 1),
             (df_count['Name'] == 1) & (df_count['Prof'] >= 2),
             (df_count['Name'] >= 2) & (df_count['Prof'] == 1),
             (df_count['Name'] >= 2) & (df_count['Prof'] >= 2)
            ]

choice_list = ['1_to_1',
               '1_to_M',
               'M_to_1',
               'M_to_M'
              ]

df_count['relation'] = np.select(cond_list, choice_list)              

第二步:设置Prof如下:

我们使用.unique() 来获取Profjoin 的唯一值

sort=False in .groupby() 保持原始顺序。

df_prof = (df.groupby(['Name', 'Location'], as_index=False, sort=False)['Prof']
             .agg(lambda x: ', '.join(x.unique())))

第 3 步:将它们合并在一起

df_final = df_prof.merge(df_count[['Location', 'relation']], on='Location')

结果:

df_count

print(df_count)

  Location  Name  Prof relation
0        A     1     1   1_to_1
1        B     1     2   1_to_M
2        C     2     1   M_to_1
3        D     2     2   M_to_M

df_prof

print(df_prof)

      Name Location      Prof
0    ahmed        A       doc
1  mohamed        B  eng, doc
2   hassan        C       eng
3      ali        C       eng
4     nice        D       doc
5      bad        D       eng

df_final

print(df_final)

      Name Location      Prof relation
0    ahmed        A       doc   1_to_1
1  mohamed        B  eng, doc   1_to_M
2   hassan        C       eng   M_to_1
3      ali        C       eng   M_to_1
4     nice        D       doc   M_to_M
5      bad        D       eng   M_to_M

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-06
    • 1970-01-01
    • 1970-01-01
    • 2021-03-20
    • 1970-01-01
    • 1970-01-01
    • 2020-08-17
    相关资源
    最近更新 更多