我有一个pandas数据框,my_labels其中包含一个包含字符串的列:'A', 'B', 'C', 'D', 'E'.我想计算每个字符串的出现次数,然后将计数的数量除以所有计数的总和.我想在熊猫中这样做:
func = lambda x: x.size() / x.sum()
data = frame.groupby('my_labels').apply(func)
Run Code Online (Sandbox Code Playgroud)
此代码抛出错误,'DataFrame对象没有属性'size'.如何在Pandas中应用函数来计算?
mon*_*kut 37
apply将函数应用于每个值,而不是系列,并接受kwargs.所以,这些值没有这个.size()方法.
也许这会奏效:
from pandas import *
d = {"my_label": Series(['A','B','A','C','D','D','E'])}
df = DataFrame(d)
def as_perc(value, total):
return value/float(total)
def get_count(values):
return len(values)
grouped_count = df.groupby("my_label").my_label.agg(get_count)
data = grouped_count.apply(as_perc, total=df.my_label.count())
Run Code Online (Sandbox Code Playgroud)
此.agg()方法采用一个应用于groupby对象的所有值的函数.
尝试:
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
Run Code Online (Sandbox Code Playgroud)
输出:
0 1
0
A 2 0.285714
B 1 0.142857
C 1 0.142857
D 2 0.285714
E 1 0.142857
Run Code Online (Sandbox Code Playgroud)
从Pandas 0.22版开始,还存在apply:的替代方法pipe,它可能比使用速度快得多apply(您也可以检查此问题以了解这两种功能之间的更多差异)。
例如:
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
Run Code Online (Sandbox Code Playgroud)
该apply版本
df.groupby('my_label').apply(lambda grp: grp.count() / df.shape[0])
Run Code Online (Sandbox Code Playgroud)
给
my_label
my_label
A 0.285714
B 0.142857
C 0.142857
D 0.285714
E 0.142857
Run Code Online (Sandbox Code Playgroud)
和pipe版本
df.groupby('my_label').pipe(lambda grp: grp.size() / grp.size().sum())
Run Code Online (Sandbox Code Playgroud)
产量
my_label
A 0.285714
B 0.142857
C 0.142857
D 0.285714
E 0.142857
Run Code Online (Sandbox Code Playgroud)
因此,值是相同的,但是,时序差异很大(至少对于这个小的数据帧而言):
%timeit df.groupby('my_label').apply(lambda grp: grp.count() / df.shape[0])
100 loops, best of 3: 5.52 ms per loop
Run Code Online (Sandbox Code Playgroud)
和
%timeit df.groupby('my_label').pipe(lambda grp: grp.size() / grp.size().sum())
1000 loops, best of 3: 843 µs per loop
Run Code Online (Sandbox Code Playgroud)
将其包装为一个函数也很简单:
def get_perc(grp_obj):
gr_size = grp_obj.size()
return gr_size / gr_size.sum()
Run Code Online (Sandbox Code Playgroud)
现在你可以打电话
df.groupby('my_label').pipe(get_perc)
Run Code Online (Sandbox Code Playgroud)
屈服
my_label
A 0.285714
B 0.142857
C 0.142857
D 0.285714
E 0.142857
Run Code Online (Sandbox Code Playgroud)
但是,对于这种特殊情况,您甚至不需要groupby,而可以这样使用value_counts:
df['my_label'].value_counts(sort=False) / df.shape[0]
Run Code Online (Sandbox Code Playgroud)
屈服
A 0.285714
C 0.142857
B 0.142857
E 0.142857
D 0.285714
Name: my_label, dtype: float64
Run Code Online (Sandbox Code Playgroud)
对于这个小的数据帧,它非常快
%timeit df['my_label'].value_counts(sort=False) / df.shape[0]
1000 loops, best of 3: 770 µs per loop
Run Code Online (Sandbox Code Playgroud)
正如@anmol指出的那样,最后一条语句也可以简化为
df['my_label'].value_counts(sort=False, normalize=True)
Run Code Online (Sandbox Code Playgroud)
关于“大小”的问题,大小不是数据帧上的函数,而是一个属性。因此,与其使用 size(),不如使用普通大小
除此之外,这样的方法应该有效
def doCalculation(df):
groupCount = df.size
groupSum = df['my_labels'].notnull().sum()
return groupCount / groupSum
dataFrame.groupby('my_labels').apply(doCalculation)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
75170 次 |
| 最近记录: |