Python熊猫将功能应用于分组的数据框

时间:2020-04-18 13:03:56

标签: python pandas

我正在处理Titanic数据集
可以为多名乘客发行一张票,即e。几个乘客可能有相同的机票号
所有这些乘客的“票价”功能将相同,并且等于整个票价
例如,如果有4位乘客乘一张机票旅行,则票价可以是40美元,但每位乘客票价应为10美元。
因此,应该将机票价格除以机票频率以计算每位乘客的票价。
但是还有一件事:婴儿需要支付2美元,而12岁以下的儿童则需要支付成人一半的费用。
因此,我试图在考虑儿童票价的情况下计算出每个成年人在机票中支付的价格。
这是一个示例数据框:

df = pd.DataFrame({'Age': [0.5,5,20,21,22,23,24], 'Fare': [17,17,17,40,40,40,40], 'TicketNum': [1,1,1,2,2,2,2]})
       Age      Fare    TicketNum
0 0.5 17 1
1 5.0 17 1
2 20.0 17 1
3 21.0 40 2
4 22.0 40 2
5 23.0 40 2
6 24.0 40 2

首先,我要执行此功能:

def fare_calc(x):
    ticket_fare = x['Fare'].mean()

    group_size = x.shape[0]
    babies_count = x[x['Age']<1].count()
    child_count = x[x['Age']<12].count()
    adult_count = group_size - babies_count - child_count
    adult_fare = (ticket_fare - babies_count * 2) / (adult_count + child_count*0.5)
    return adult_fare

然后我尝试:

df['TicketFreq'] = df.groupby('TicketNum')['TicketNum'].transform('count')
df['Fare2'] = df[df.TicketFreq>1].groupby(['TicketNum'])['Age','Fare'].agg(fare_calc)

并得到一个错误:
ValueError:传递的项目数错误2,展示位置表示1

所需的输出如下:

       Age      Fare    TicketNum    Fare2
0 0.5 17 1 10
1 5.0 17 1 10
2 20.0 17 1 10
3 21.0 40 2 10
4 22.0 40 2 10
5 23.0 40 2 10
6 24.0 40 2 10

3 个答案:

答案 0 :(得分:1)

嘿,您的公式编制者似乎错了,但是当您用fare_calc替换.agg调用并删除您指定的两列时,.apply函数就会执行。参见下面的示例

df[df.TicketFreq>1].groupby(['TicketNum']).apply(fare_calc)

此外,您的功能仅需要进行一些更改。
要获取babie_count和child_count的数字计数,您需要指定一个列以仅获取一个整数

def fare_calc(x):
    ticket_fare = x['Fare'].mean()
    group_size = x.shape[0]
    babies_count = x[x['Age']<1]['Age'].count()
    child_count = x[x['Age']<12]['Age'].count()
    adult_count = group_size - babies_count - child_count
    adult_fare = (ticket_fare - babies_count * 2) / (adult_count + child_count * 0.5)
    return adult_fare

答案 1 :(得分:1)

这是我的解决方法

我使用pd.Series().repeat()函数创建按列的一系列值。

顺便说一句,您忘记了使用(df['Age']<12) & (df['Age']>1)从child_count中排除babies_count

def fare_calc(x):
    group_size   = x.shape[0]
    ticket_fare  = pd.Series(x['Fare'].mean().repeat(group_size))
    babies_count = x[x['Age']<1 ]['Age'].count()
    child_count  = x[(df['Age']<12) & (df['Age']>1)]['Age'].count()
    adult_count  = group_size - babies_count - child_count
    adult_fare   = (ticket_fare - babies_count * 2) / (adult_count + child_count * 0.5)
    return adult_fare

最后,仅使用apply提取由.values函数创建的堆叠Series的值,以防止发生“不兼容索引” TypeError。

df['Fare2'] = df[df.TicketFreq>1].groupby(['TicketNum']).apply(fare_calc).values

print(df)
    Age  Fare  TicketNum  TicketFreq  Fare2
0   0.5    17          1           3   10.0
1   5.0    17          1           3   10.0
2  20.0    17          1           3   10.0
3  21.0    40          2           4   10.0
4  22.0    40          2           4   10.0
5  23.0    40          2           4   10.0
6  24.0    40          2           4   10.0

编辑1:前一个功能的直观版本:

import pandas as pd

df = pd.DataFrame({'Age': [0.5,5,20,21,22,23,24], 'Fare': [17,17,17,40,40,40,40], 'TicketNum': [1,1,1,2,2,2,2]})
df['TicketFreq'] = df.groupby('TicketNum')['TicketNum'].transform('count')

def fare_calc(x):
    group_size       = x.shape[0]
    x['ticket_fare'] = x['Fare'].mean()
    babies_count     = x[x['Age']<1 ]['Age'].count()
    child_count      = x[(df['Age']<12) & (df['Age']>1)]['Age'].count()
    adult_count      = group_size - babies_count - child_count
    x['adult_fare']  = (x['ticket_fare'] - babies_count * 2) / (adult_count + child_count * 0.5)
    return x['adult_fare']

df['Fare2'] = df[df.TicketFreq>1].groupby(['TicketNum']).apply(fare_calc).values

print(df)
    Age  Fare  TicketNum  TicketFreq  Fare2
0   0.5    17          1           3   10.0
1   5.0    17          1           3   10.0
2  20.0    17          1           3   10.0
3  21.0    40          2           4   10.0
4  22.0    40          2           4   10.0
5  23.0    40          2           4   10.0
6  24.0    40          2           4   10.0

编辑2:在函数内部直接创建“ Fare2”的地方更简单

import pandas as pd

df = pd.DataFrame({'Age': [0.5,5,20,21,22,23,24], 'Fare': [17,17,17,40,40,40,40], 'TicketNum': [1,1,1,2,2,2,2]})
df['TicketFreq'] = df.groupby('TicketNum')['TicketNum'].transform('count')

def fare_calc(x):
    group_size       = x.shape[0]
    ticket_fare      = x['Fare'].mean()
    babies_count     = x[x['Age']<1 ]['Age'].count()
    child_count      = x[(df['Age']<12) & (df['Age']>1)]['Age'].count()
    adult_count      = group_size - babies_count - child_count
    x['Fare2']       = (ticket_fare - babies_count * 2) / (adult_count + child_count * 0.5)
    return x

df = df[df.TicketFreq>1].groupby(['TicketNum']).apply(fare_calc)

print(df)
    Age  Fare  TicketNum  TicketFreq  Fare2
0   0.5    17          1           3   10.0
1   5.0    17          1           3   10.0
2  20.0    17          1           3   10.0
3  21.0    40          2           4   10.0
4  22.0    40          2           4   10.0
5  23.0    40          2           4   10.0
6  24.0    40          2           4   10.0

答案 2 :(得分:0)

一个较小但紧迫的问题是,在您的最后一行代码中,['Age', 'Fare']应该为[['Age', 'Fare']],因为您希望使用列名列表进行索引。

主要问题是您编写了fare_calc()才能在整个DataFrame上工作,但是传递给df.agg()的函数将分别应用于每个列。

相关问题