【问题标题】:How to group rows together based on conditions from a list? Pandas如何根据列表中的条件将行分组在一起?熊猫
【发布时间】:2021-11-10 18:19:59
【问题描述】:

如果行在某些列中具有匹配的值,我希望能够将它们组合为一个,但是我只希望在值在列表中时将它们分组。例如,

team_sports = ['football', 'basketball']

view of df

country    sport      age
USA       football    21
USA       football    28
USA       golf        20
USA       golf        44
China     football    30
China     basketball  22
China     basketball  41

wanted outcome
country    sport      age
USA       football    21,28
USA       golf        20
USA       golf        44
China     football    30
China     basketball  22,41

The attempt I made was,

team_sports = ['football', 'basketball']

for i in df['Sport']:
  if i in team_sports:
     group_df= df.groupby(['Country', 'Sport'])['Age'].apply(list).reset_index() 

这需要很长时间才能运行,我正在使用的数据库有 100,000 行。

非常感谢任何帮助,谢谢

【问题讨论】:

  • 你为什么一遍又一遍地这样做。 group_df= df.groupby(['Country', 'Sport'])['Age'].apply(list).reset_index()不是第一次给你预期的结果吗?
  • @HenryEcker 我不确定你的意思,但我输入了一个 for,因此它不会将不同运动的行组合在一起,例如上面的高尔夫。如果我误解了,请纠正我。
  • 我明白了,我错过了仅对列表中的行进行分组的部分。顺序重要吗?您是否需要它们按照它们出现的顺序排列,或者只要所有结果都存在,顺序就无关紧要了吗?
  • @HenryEcker 顺序无所谓,只要有结果就行了

标签: pandas database group-by


【解决方案1】:

更直接的方法是根据sportsisinteam_sports 列表所在的行分离DataFrame。 groupby aggregate 分开然后concat 一起回来:

team_sports = ['football', 'basketball']

m = df['sport'].isin(team_sports)
cols = ['country', 'sport']
group_df = pd.concat([
    # Group those that do match condition
    df[m].groupby(cols, as_index=False)['age'].agg(list),
    # Leave those that don't match condition as is
    df[~m]
], ignore_index=True).sort_values(cols)

*sort_values 是可选的,可以将国家和体育重新组合在一起

group_df:

  country       sport       age
0   China  basketball  [22, 41]
1   China    football      [30]
2     USA    football  [21, 28]
3     USA        golf        20
4     USA        golf        44

不太直接的方法是使用isin + cumsum,根据值是否在团队运动列表中创建新的分组级别:

team_sports = ['football', 'basketball']

group_df = (
    df.groupby(
        ['country', 'sport',
         (~df['sport'].sort_values().isin(team_sports)).cumsum().sort_index()],
        as_index=False,
        sort=False
    )['age'].agg(list)
)

group_df:

  country       sport       age
0     USA    football  [21, 28]
1     USA        golf      [20]
2     USA        golf      [44]
3   China    football      [30]
4   China  basketball  [22, 41]

如何创建组:

team_sports = ['football', 'basketball']

print(pd.DataFrame({
    'country': df['country'],
    'sport': df['sport'],
    'not_in_team_sports': (~df['sport'].sort_values()
                           .isin(team_sports)).cumsum().sort_index()
}))
  country       sport  not_in_team_sports
0     USA    football                   0
1     USA    football                   0
2     USA        golf                   1  # golf 1
3     USA        golf                   2  # golf 2 (not in the same group)
4   China    football                   0
5   China  basketball                   0
6   China  basketball                   0

*sort_values 在这里是必需的,这样sport 组不会被不在列表中的运动打断。

df = pd.DataFrame({
    'country': ['USA', 'USA', 'USA'],
    'sport': ['football', 'golf', 'football'],
    'age': [21, 28, 20]
})
team_sports = ['football', 'basketball']

print(pd.DataFrame({
    'country': df['country'],
    'sport': df['sport'],
    'not_sorted': (~df['sport'].isin(team_sports)).cumsum(),
    'sorted': (~df['sport'].sort_values()
                           .isin(team_sports)).cumsum().sort_index()
}))
  country     sport  not_sorted  sorted
0     USA  football           0       0
1     USA      golf           1       1
2     USA  football           1       0  # football 1 (separate group if not sorted)

排序确保足球齐头并进,因此不会发生这种情况


设置:

import pandas as pd

df = pd.DataFrame({
    'country': ['USA', 'USA', 'USA', 'USA', 'China', 'China', 'China'],
    'sport': ['football', 'football', 'golf', 'golf', 'football', 'basketball',
              'basketball'],
    'age': [21, 28, 20, 44, 30, 22, 41]
})

【讨论】:

    猜你喜欢
    • 2022-01-25
    • 2021-08-27
    • 2021-09-12
    • 2023-01-23
    • 2017-12-18
    • 1970-01-01
    • 2023-02-15
    • 2020-04-09
    • 1970-01-01
    相关资源
    最近更新 更多