熊猫:通过自定义功能对数据框进行分组

时间:2020-05-18 17:02:00

标签: python pandas dataframe pandas-groupby

我有一个字符串元组。我想按字符串的长度分组。这可以通过

完成
import pandas as pd

data = 'aaa', 'bb', 'ccc', 'dd', 'eeee', 'ff'

df = pd.DataFrame(data, columns=['string'])

def length(index):
    return len(df.at[index, 'string'])

for length, group in df.groupby(by=length):
    print(group)
    print('(length:', str(length) + ')', end='\n\n')
  string
1     bb
3     dd
5     ff
(length: 2)

  string
0    aaa
2    ccc
(length: 3)

  string
4   eeee
(length: 4)

现在我的问题:

  1. 我真的需要创建一个函数len(df.at[index, column]以便按长度对单列数据帧进行分组吗?

  2. 这是分组自定义功能的最佳方法吗?该解决方案(适用于具有140,000个单词的文件)与带有字典的纯Python解决方案之间的比较表明,该解决方案的运行时间为32.5(!)秒,而Python解决方案的运行时间为0.95秒。

4 个答案:

答案 0 :(得分:0)

pandas DataFrame和Series已经具有.hist()方法。 您可以简单地做到

import pandas as pd

data = 'aaa', 'bb', 'ccc', 'dd', 'eeee', 'ff'
df = pd.DataFrame(data, columns=['password'])

df['password'].str.len().hist()

或者,如果不进行df处理,也可以(作为解决方案1),

pd.Series(data).str.len().hist()

结帐documentation,了解如何自定义情节

答案 1 :(得分:0)

我们有series groupby

for x, y in df.groupby(df.string.str.len()):
    print(y)
    print('(length:', str(x) + ')', end='\n\n')

  string
1     bb
3     dd
5     ff
(length: 2)
  string
0    aaa
2    ccc
(length: 3)
  string
4   eeee
(length: 4)

答案 2 :(得分:0)

免责声明:这实际上是评论,但可以作为正确格式的答案。

Ben的回答在某种程度上回答了您的问题1:不,您不需要创建函数来进行分组。更不用说您的自定义函数可能会很慢,因为它每次都会调用at访问。通过性能比较可以看出:

# random data
np.random.seed(1)
data= [''.join(np.random.choice(list('abcdefgh'),np.random.randint(5,10)) )
    for _ in range(100000)]
df = pd.DataFrame(data, columns = ['string'])

def length(index):
    return len(df.at[index, 'string'])

# Your solution:
%%time
x=0
for length, group in df.groupby(length):
    x+=length
# CPU times: user 451 ms, sys: 0 ns, total: 451 ms
# Wall time: 450 ms


# Ben's solution
%%time
x=0
for x, y in df.groupby(df.string.str.len()):
    x+=length

# CPU times: user 35.5 ms, sys: 0 ns, total: 35.5 ms
# Wall time: 34.2 ms

注意,这两个函数在for循环内使用简单的功能。在您的代码中,print将成为瓶颈,因为打印到终端总是很慢。我高度怀疑纯Python分组功能是否可以和Ben的解决方案一样快。请发布该解决方案,我很高兴得知自己对此做错了。

答案 3 :(得分:0)

以Ben和Quang Hoang的答案为基础:我需要一个通用的按功能分组行解决方案(该数学术语为“等价类”)。要考虑的一件事是,并非所有函数都具有lenpandas.Series.str.len之类的“向量化”等效项。

解决方案:

def groupby(df, projection=lambda x: x, label=0):  
    '''
    group dataframe into equivalence classes
    see http://en.wikipedia.org/wiki/Equivalence_relation
    '''
    return df.groupby(by=df.loc[:, label].apply(projection), sort=False)

现在在上述文件中使用groupby(df, len)并使用140,000个单词需要0.45秒而不是32.5秒。这意味着pandas group-by解决方案的速度是使用字典的纯Python解决方案的两倍。感谢Ben和Quang Hoang的投入。