【问题标题】:panda aggregate by functionspanda 按函数聚合
【发布时间】:2019-01-31 01:11:59
【问题描述】:

我有如下数据:

id  movie   details value
5   cane1   good    6
5   wind2   ok  30.3
5   wind1   ok  18
5   cane1   good    2
5   cane22  ok  4
5   cane34  good    7
5   wind2   ok  2

我想要具有以下条件的输出:

如果电影名称以“cane”开头 - 求和

如果电影名称以“风”开头 - 计算出现次数。

所以 - 最终输出将是:

id  movie   value
5   cane1   8
5   cane22  4
5   cane34  7
5   wind1   1
5   wind2   2

我尝试使用:

movie_df.groupby(['id']).apply(aggr)

def aggr(x):
    if x['movie'].str.startswith('cane'):
        y = x.groupby(['value']).sum()

    else:
         y = x.groupby(['movie']).count()

    return y

但它不起作用。有人可以帮忙吗?

【问题讨论】:

  • 我看到 cane 的值 = 19,即 6 + 2 + 4 + 7。

标签: python pandas dataframe


【解决方案1】:

您应该尽可能以矢量化操作为目标。

您可以计算 2 个结果,然后将它们连接起来。

mask = df['movie'].str.startswith('cane')

df1 = df[mask].groupby('movie')['value'].sum()
df2 = df[~mask].groupby('movie').size()

res = pd.concat([df1, df2], ignore_index=0)\
        .rename('value').reset_index()

print(res)

    movie  value
0   cane1    8.0
1  cane22    4.0
2  cane34    7.0
3   wind1    1.0
4   wind2    2.0

【讨论】:

  • 感谢您的回复!但是-我在最初的问题中意识到我没有正确提供输出。我稍微编辑了这个问题。你能看看吗?基本上 - 我需要输出中的所有电影(即 cane1、cane22、cane34、wind1、wind2 等)
  • 谢谢!现在我只需要 id 列,因为我也必须按 id 分组。真的很感激!
  • 您尚未在问题中确定 id 的逻辑。使用groupby(['id', 'movie']) 或使用first,如@Retiefasaurus 的回答。
【解决方案2】:

可能有多种方法可以做到这一点。一种方法是先按电影名称的开头进行过滤,然后再聚合和合并。

cane = movie_df[movie_df['movie'].str.startswith('cane1')]
wind = movie_df[movie_df['movie'].str.startswith('wind')]

cane_sum = cane.groupby(['id']).agg({'movie':'first', 'value':'sum'}).reset_index()
wind_count = wind.groupby(['id']).agg({'movie':'first', 'value':'count'}).reset_index()

pd.concat([cane_sum, wind_count])

【讨论】:

  • 感谢您的回复!但是-我在最初的问题中意识到我没有正确提供输出。我稍微编辑了这个问题。你能看看吗?基本上 - 我需要输出中的所有电影(即 cane1、cane22、cane34、wind1、wind2 等)
【解决方案3】:

首先,你需要进行字符串操作。我想在你的情况下你不想要电影名称中的数字。使用pandas applying regex to replace values 讨论的解决方案。 然后你在新系列上调用 groupby()。

仅供参考:有些电影名称只有数字;在这种情况下,您需要使用更新功能。 https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.update.html

【讨论】:

    【解决方案4】:

    我将首先创建一个定义所需组的列。对于手头的示例,可以使用

    df['group'] = df.movie.transform(lambda x : x[:4])

    下一步是按此列分组

    df.groupby('group').apply(agg_fun)
    

    使用以下聚合函数

    def agg_fun(grp):
        if grp.name == "cane":
            value=grp.value.sum()
        else:
            value=grp.value.count()
        return value
    

    这段代码的输出是

    group
    cane    19.0
    wind     3.0
    

    【讨论】:

      猜你喜欢
      • 2021-06-16
      • 2022-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-11
      • 1970-01-01
      • 1970-01-01
      • 2016-09-11
      相关资源
      最近更新 更多