Python 熊猫:按自定义函数对数据帧进行分组

Python 熊猫:按自定义函数对数据帧进行分组,python,pandas,dataframe,pandas-groupby,Python,Pandas,Dataframe,Pandas Groupby,我有一组字符串。我想按字符串的长度分组。这可以通过 将熊猫作为pd导入 数据='aaa','bb','ccc','dd','eeee','ff' df=pd.DataFrame(数据,列=['string']) def长度(索引): 返回len(df.at[索引'string']) 对于长度,在df.groupby中分组(按=长度): 打印(组) 打印('(长度:',str(长度)+'),结束='\n\n') 现在我的问题是: 我真的需要创建一个函数len(df.at[index,column

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

将熊猫作为pd导入
数据='aaa','bb','ccc','dd','eeee','ff'
df=pd.DataFrame(数据,列=['string'])
def长度(索引):
返回len(df.at[索引'string'])
对于长度,在df.groupby中分组(按=长度):
打印(组)
打印('(长度:',str(长度)+'),结束='\n\n')
现在我的问题是:

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

  • 这是按自定义函数分组的最佳方式吗?此解决方案(应用于140000字的文件)与带字典的纯Python解决方案之间的比较表明,此解决方案运行需要32.5(!)秒,而Python解决方案运行需要0.95秒


  • 熊猫数据帧和系列已具有
    .hist()
    方法。 你可以简单地做

    将熊猫作为pd导入
    数据='aaa','bb','ccc','dd','eeee','ff'
    df=pd.DataFrame(数据,列=['password'])
    df['password'].str.len().hist()
    
    或者,如果不制作df对您来说是好的(作为您的解决方案1),那么

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

    有关如何自定义绘图的签出数据帧和系列已具有
    .hist()
    方法。 你可以简单地做

    将熊猫作为pd导入
    数据='aaa','bb','ccc','dd','eeee','ff'
    df=pd.DataFrame(数据,列=['password'])
    df['password'].str.len().hist()
    
    或者,如果不制作df对您来说是好的(作为您的解决方案1),那么

    pd.Series(data.str.len().hist())
    
    查看如何自定义绘图

    我们有
    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)
    
    我们有
    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)
    

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

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

    # 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
    循环中使用了简单的函数。在您的代码中,
    打印
    将成为瓶颈,因为打印到终端总是很慢。我非常怀疑纯Python分组函数是否能像Ben的解决方案那样快。请发布该解决方案,我很高兴得知我正在编写g关于这一点。

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

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

    # 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
    循环中使用了简单的函数。在您的代码中,
    打印
    将成为瓶颈,因为打印到终端总是很慢。我非常怀疑纯Python分组函数是否能像Ben的解决方案那样快。请发布该解决方案,我很高兴得知我正在编写关于这个问题,Taking Ben和Quang Hoang的回答和构建:我需要一个通用的函数行组(数学术语是“等价类”)。有一件事要考虑的是,不是所有函数都有一个“矢量化”等价物,如<代码> Le< <代码>和<代码>熊猫。 解决方案:

    def groupby(df,投影=lambda x:x,标签=0):
    '''
    将数据帧分组为等价类
    看见http://en.wikipedia.org/wiki/Equivalence_relation
    '''
    返回df.groupby(by=df.loc[:,label].apply(投影),sort=False)
    

    现在使用
    groupby(df,len)
    在上面提到的140000字的文件上花费0.45秒,而不是32.5秒。这意味着pandas group-by解决方案的速度是使用字典的纯Python解决方案的两倍。感谢Ben和Quang-Hoang的输入。

    接受Ben和Quang-Hoang的答案并以此为基础:我需要一个通用的group-rows-by-f函数表达式(数学术语)是“等价类”。有一点需要考虑的是,不是所有函数都有一个“矢量化”等价物,如<代码> Le< <代码>和<代码>熊猫。 解决方案:

    def groupby(df,投影=lambda x:x,标签=0):
    '''
    将数据帧分组为等价类
    看见http://en.wikipedia.org/wiki/Equivalence_relation
    '''
    返回df.groupby(by=df.loc[:,label].apply(投影),sort=False)
    

    现在使用
    groupby(df,len)
    在上面提到的140000字的文件上,需要0.45秒,而不是32.5秒。这意味着pandas group by解决方案的速度是使用字典的纯Python解决方案的两倍。感谢Ben和Quang Hoang的输入。

    对不起,我的问题不是关于绘图,而是关于分组。我将编辑简介,使其更清晰抱歉,我的问题不是关于绘图,而是关于分组。我将编辑简介以使其更清楚。抱歉,使用系列而不是数据帧不会使分组更快(问题2),也不会回答问题1。抱歉,使用系列而不是数据帧不会使分组更快(问题2)也不回答问题#1.你完全正确,我没有仔细阅读本的解决方案。他和你的回答实际上回答了我的两个问题。本的
    str.len()
    当然只适用于矢量化函数。我将发布一个更新,并提供一个通用解决方案。你完全正确,我没有仔细阅读本的解决方案。他和你的回答实际上回答了我的两个问题。本的
    str.len()
    当然只适用于矢量化函数。我将发布一个带有通用解决方案的更新。