Pandas的groupby从多个列创建数值列表

huangapple go评论88阅读模式
英文:

Pandas groupby create a list of values from several columns

问题

  1. 我有一个数据框
  2. df = ID C1 C2 C3 C4
  3. 1 a b r q
  4. 1 b e g h
  5. 2 p a z p
  6. 1 r a n m
  7. 我想要按ID获取C1C2中的数值列表
  8. 所以我会得到
  9. out = ID l
  10. 1 [a,b,r,e]
  11. 2

  12. 最好的方法是什么

英文:

I have a dataframe

  1. df = ID C1 C2 C3 C4
  2. 1 a b r q
  3. 1 b e g h
  4. 2 p a z p
  5. 1 r a n m

I want to get list of values in C1, C2 per ID.
So I will have:

  1. out = ID l
  2. 1 [a,b,r,e]
  3. 2

What is the best way to do so?

答案1

得分: 2

你可以将数据框展平,然后按ID分组,最后获取唯一的数值:

  1. df.melt('ID', value_name='l').groupby('ID', as_index=False)['l'].unique()
  2. ID l
  3. 0 1 [a, b, r, e]
  4. 1 2

更新

如果你想要为C1和C2各有一个单独的列:

  1. (df.melt('ID', var_name='col', value_name='l')
  2. .groupby(['ID', 'col'], as_index=False)['l']
  3. .apply(lambda x: np.unique(x).tolist())
  4. .pivot(index='ID', columns='col', values='l')
  5. .rename_axis(columns=None).reset_index())
  6. ID C1 C2
  7. 0 1 [a, b, r] [b, e, a]
  8. 1 2

    [a]

英文:

You can flatten your dataframe then group by ID and finally get unique values:

  1. >>> df.melt('ID', value_name='l').groupby('ID', as_index=False)['l'].unique()
  2. ID l
  3. 0 1 [a, b, r, e]
  4. 1 2

Update

> And if I want a seperate column for C1 and C2

  1. >>> (df.melt('ID', var_name='col', value_name='l')
  2. .groupby(['ID', 'col'], as_index=False)['l']
  3. .apply(lambda x: np.unique(x).tolist())
  4. .pivot(index='ID', columns='col', values='l')
  5. .rename_axis(columns=None).reset_index())
  6. ID C1 C2
  7. 0 1 [a, b, r] [b, e, a]
  8. 1 2

    [a]

答案2

得分: 0

使用lambda函数与numpy.unique - 输出已排序:

  1. df1 = (df.groupby('ID')[['C1','C2']].apply(lambda x: np.unique(x).tolist())
  2. .reset_index(name='l'))
  3. print (df1)
  4. ID l
  5. 0 1 [a, b, e, r]
  6. 1 2 [a, p]

或者使用unique - 输出与原始顺序一致:

  1. df1 = (df.groupby('ID')[['C1','C2']].apply(lambda x: pd.unique(np.ravel(x)).tolist())
  2. .reset_index(name='l'))
  3. print (df1)
  4. ID l
  5. 0 1 [a, b, e, r]
  6. 1 2

另一种方法是删除缺失值和重复项:

  1. df1 = (df.melt(id_vars='ID', value_vars=['C1','C2'], value_name='l')
  2. .drop_duplicates(['ID','l'])
  3. .dropna(subset=['l'])
  4. .groupby('ID')['l']
  5. .agg(list)
  6. .reset_index())
  7. print (df1)
  8. ID l
  9. 0 1 [a, b, r, e]
  10. 1 2

编辑: 要分别处理列,请使用GroupBy.agg:

  1. df2 = df.groupby('ID')[['C1','C2']].agg(lambda x: np.unique(x).tolist()).reset_index()
  2. print (df2)
  3. ID C1 C2
  4. 0 1 [a, b, r] [a, b, e]
  5. 1 2

    [a]

英文:

Use lambda function with numpy.unique - output is sorted:

  1. df1 = (df.groupby('ID')[['C1','C2']].apply(lambda x: np.unique(x).tolist())
  2. .reset_index(name='l'))
  3. print (df1)
  4. ID l
  5. 0 1 [a, b, e, r]
  6. 1 2 [a, p]

Or with unique - output is with original order:

  1. df1 = (df.groupby('ID')[['C1','C2']].apply(lambda x: pd.unique(np.ravel(x)).tolist())
  2. .reset_index(name='l'))
  3. print (df1)
  4. ID l
  5. 0 1 [a, b, e, r]
  6. 1 2

Another idea with remove missing values and duplicates:

  1. df1 = (df.melt(id_vars='ID', value_vars=['C1','C2'], value_name='l')
  2. .drop_duplicates(['ID','l'])
  3. .dropna(subset=['l'])
  4. .groupby('ID')['l']
  5. .agg(list)
  6. .reset_index())
  7. print (df1)
  8. ID l
  9. 0 1 [a, b, r, e]
  10. 1 2

EDIT: For separate columns use GroupBy.agg:

  1. df2 = df.groupby('ID')[['C1','C2']].agg(lambda x: np.unique(x).tolist()).reset_index()
  2. print (df2)
  3. ID C1 C2
  4. 0 1 [a, b, r] [a, b, e]
  5. 1 2

    [a]

huangapple
  • 本文由 发表于 2023年2月14日 20:42:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/75447996.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定