在 Pandas 中如何使用带有 HAVING 子句的 GROUP_CONCAT?

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

How to use GROUP_CONCAT with HAVING clause in Pandas?

问题

你可以使用Pandas来实现与上述SQL查询相同的结果,代码如下:

  1. import pandas as pd
  2. # 创建DataFrame
  3. data = {'name': ['John', 'Joe', 'Joe', 'Marcus', 'John', 'John'],
  4. 'type': [1, 0, 1, 0, 2, 0]}
  5. df = pd.DataFrame(data)
  6. # 使用groupby、agg和join来获取结果
  7. result = df.groupby('name')['type'].agg(lambda x: ','.join(x.astype(str)) if len(x) > 1 else x.astype(str)).reset_index()
  8. # 将列名改为小写
  9. result.columns = result.columns.str.lower()
  10. result

这段代码会产生一个Pandas DataFrame,其中'name'列是分组的名称,'type'列包含相应的组合值,只有在每个分组中有多个值时才会进行组合。

英文:

Suppose I have a dataframe like this:

name type
John 1
Joe 0
Joe 1
Marcus 0
John 2
John 0

How can I use Pandas to have the same result as:

  1. SELECT name, GROUP_CONCAT(type)
  2. FROM df
  3. GROUP BY name
  4. HAVING COUNT(*)>1;
name type
john 0,1,2
joe 0,1

答案1

得分: 2

你可以使用自定义的 groupby.agg 来实现,类似以下方式:

  1. out = (df
  2. .groupby('name', as_index=False, sort=False)['type']
  3. .agg(lambda s: ','.join(s.sort_values().astype(str)) if len(s) > 1 else None)
  4. .dropna(subset='type')
  5. )

或者:

  1. out = (df
  2. .groupby('name', as_index=False, sort=False)
  3. .agg({'type': ('type', lambda s: ','.join(s.sort_values().astype(str))),
  4. 'count': ('type', 'count')
  5. })
  6. .loc[lambda d: d.pop('count').gt(1)]
  7. )

或者:

  1. out = (df
  2. .groupby('name', as_index=False, sort=False)['type']
  3. .agg(lambda s: ','.join(s.sort_values().astype(str)))
  4. .loc[lambda d: d['type'].str.contains(',')]
  5. )

输出结果:

  1. name type
  2. 0 John 0,1,2
  3. 1 Joe 0,1
英文:

You can use a custom groupby.agg with something like:

  1. out = (df
  2. .groupby('name', as_index=False, sort=False)['type']
  3. .agg(lambda s: ','.join(s.sort_values().astype(str)) if len(s)>1 else None)
  4. .dropna(subset='type')
  5. )

Or:

  1. out = (df
  2. .groupby('name', as_index=False, sort=False)
  3. .agg(**{'type': ('type', lambda s: ','.join(s.sort_values().astype(str))),
  4. 'count': ('type', 'count')
  5. })
  6. .loc[lambda d: d.pop('count').gt(1)]
  7. )

Or:

  1. out = (df
  2. .groupby('name', as_index=False, sort=False)['type']
  3. .agg(lambda s: ','.join(s.sort_values().astype(str)))
  4. .loc[lambda d: d['type'].str.contains(',')]
  5. )

Output:

  1. name type
  2. 0 John 0,1,2
  3. 1 Joe 0,1

答案2

得分: 2

你可以尝试以下操作:

  1. out = (df[df.duplicated('name', keep=False)].astype({'type': str}).sort_values('type')
  2. .groupby('name', sort=False, as_index=False)['type'].agg(','.join))
  3. print(out)
  4. # 输出结果
  5. name type
  6. 0 Joe 0,1
  7. 1 John 0,1,2

注意:我已经将代码部分保持不变,只翻译了注释和输出结果。

英文:

You can probably do:

  1. out = (df[df.duplicated('name', keep=False)].astype({'type': str}).sort_values('type')
  2. .groupby('name', sort=False, as_index=False)['type'].agg(','.join))
  3. print(out)
  4. # Output
  5. name type
  6. 0 Joe 0,1
  7. 1 John 0,1,2

huangapple
  • 本文由 发表于 2023年5月24日 22:19:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/76324555.html
匿名

发表评论

匿名网友

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

确定