首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Apply function to pandas groupby

Apply function to pandas groupby
EN

Stack Overflow用户
提问于 2013-03-13 08:01:14
回答 4查看 148.5K关注 0票数 53

我有一个pandas数据帧,它有一个名为my_labels的列,其中包含字符串:'A', 'B', 'C', 'D', 'E'。我想计算每个字符串出现的次数,然后将计数的数量除以所有计数的总和。我试着在Pandas中这样做:

代码语言:javascript
复制
func = lambda x: x.size() / x.sum()
data = frame.groupby('my_labels').apply(func)

这段代码抛出一个错误,'DataFrame对象没有'size‘属性。我如何在Pandas中应用函数来计算这个值呢?

EN

回答 4

Stack Overflow用户

发布于 2018-01-04 16:03:05

除了As of Pandas version 0.22,还有一种替代apply的方法:pipe,它比使用apply快得多(您还可以查看this question了解这两种功能之间的更多差异)。

对于您的示例:

代码语言:javascript
复制
df = pd.DataFrame({"my_label": ['A','B','A','C','D','D','E']})

  my_label
0        A
1        B
2        A
3        C
4        D
5        D
6        E

apply版本

代码语言:javascript
复制
df.groupby('my_label').apply(lambda grp: grp.count() / df.shape[0])

给出

代码语言:javascript
复制
          my_label
my_label          
A         0.285714
B         0.142857
C         0.142857
D         0.285714
E         0.142857

pipe版本

代码语言:javascript
复制
df.groupby('my_label').pipe(lambda grp: grp.size() / grp.size().sum())

收益率

代码语言:javascript
复制
my_label
A    0.285714
B    0.142857
C    0.142857
D    0.285714
E    0.142857

因此,值是相同的,但是,计时差别很大(至少对于这个小数据帧是如此):

代码语言:javascript
复制
%timeit df.groupby('my_label').apply(lambda grp: grp.count() / df.shape[0])
100 loops, best of 3: 5.52 ms per loop

代码语言:javascript
复制
%timeit df.groupby('my_label').pipe(lambda grp: grp.size() / grp.size().sum())
1000 loops, best of 3: 843 µs per loop

然后,将其封装到一个函数中也很简单:

代码语言:javascript
复制
def get_perc(grp_obj):
    gr_size = grp_obj.size()
    return gr_size / gr_size.sum()

现在您可以调用

代码语言:javascript
复制
df.groupby('my_label').pipe(get_perc)

让位

代码语言:javascript
复制
my_label
A    0.285714
B    0.142857
C    0.142857
D    0.285714
E    0.142857

但是,对于这种特殊情况,您甚至不需要groupby,但可以像这样使用value_counts

代码语言:javascript
复制
df['my_label'].value_counts(sort=False) / df.shape[0]

让位

代码语言:javascript
复制
A    0.285714
C    0.142857
B    0.142857
E    0.142857
D    0.285714
Name: my_label, dtype: float64

对于这个小数据帧,它是相当快的

代码语言:javascript
复制
%timeit df['my_label'].value_counts(sort=False) / df.shape[0]
1000 loops, best of 3: 770 µs per loop

正如@anmol所指出的,最后一条语句也可以简化为

代码语言:javascript
复制
df['my_label'].value_counts(sort=False, normalize=True)
票数 24
EN

Stack Overflow用户

发布于 2013-03-13 09:04:35

尝试:

代码语言:javascript
复制
g = pd.DataFrame(['A','B','A','C','D','D','E'])

# Group by the contents of column 0 
gg = g.groupby(0)  

# Create a DataFrame with the counts of each letter
histo = gg.apply(lambda x: x.count())

# Add a new column that is the count / total number of elements    
histo[1] = histo.astype(np.float)/len(g) 

print histo

输出:

代码语言:javascript
复制
   0         1
0             
A  2  0.285714
B  1  0.142857
C  1  0.142857
D  2  0.285714
E  1  0.142857
票数 9
EN

Stack Overflow用户

发布于 2018-07-20 06:38:00

关于“size”的问题,size不是数据帧上的函数,而是一个属性。因此,不是使用size(),而是使用普通大小

除此之外,像这样的方法应该是可行的。

代码语言:javascript
复制
def doCalculation(df):
    groupCount = df.size
    groupSum = df['my_labels'].notnull().sum()
    
    return groupCount / groupSum

dataFrame.groupby('my_labels').apply(doCalculation)
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15374597

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档