• pandas中的groupby、transform以及pivot_table


    groupby

    import pandas as pd
    
    df = pd.DataFrame({
        "a": ['a', 'b', 'a', 'a', 'b'],
        "b": [1, 2, 3, 2, 1],
        "c": [3, 1, 5, 1, 7],
        "d": ["我", "是", "一", "条", "狗"]
    })
    
    # groupby可以同时by多个字段,组合成一个列表
    # 如果只by一个字段,那么除了列表之外、也可以只写一个字符串,即by="a"
    print(df.groupby(by=["a"]))  # <pandas.core.groupby.generic.DataFrameGroupBy object at 0x000001A7B31F8700>
    
    # 此时得到的是一个DataFrameGroupBy对象,我们可以对这个对象执行聚合操作
    # 比如sum、count、mean等等
    print(df.groupby(by="a").sum())
    """
       b  c
    a      
    a  6  9
    b  3  8
    """
    print(df.groupby(by="a").count())
    """
       b  c  d
    a         
    a  3  3  3
    b  2  2  2
    """
    # 我们对于sum这种来讲,显然是需要数值类型的,因此pandas会自动选择数值类型的列进行聚合
    # 但是对count这种就没有要求了,会选择所有的列
    
    # 但是我们发现,在聚合的时候,参数by指定的列会变成索引,那么如何让它们不变成索引呢
    print(df.groupby(by="a", as_index=False).sum())
    """
       a  b  c
    0  a  6  9
    1  b  3  8
    """
    # 通过参数as_index=False即可,让by指定的列不作为索引
    
    
    # 另外聚合的时候,我们也可以这么做
    print(df.groupby(by="a", as_index=False).agg("sum"))
    """
       a  b  c
    0  a  6  9
    1  b  3  8
    """
    # df.groupby(by="a", as_index=False).agg("sum") 和 df.groupby(by="a", as_index=False).sum()是等价的
    # 同理:df.groupby().agg("count")、df.groupby().agg("mean")等等也是一样的
    # 只要df.groupby().xxx()可以调用的,都可以通过df.groupby().agg("xxx")调用
    
    # 另外最重要的一点是,agg里面还可以指定函数,比如:sum、np.sum
    print(df.groupby(by="a", as_index=False).agg(sum))
    """
       a  b  c
    0  a  6  9
    1  b  3  8
    """
    # 当然我们自定义的函数也是可以的
    print(df.groupby(by="a", as_index=False).agg(lambda x: sum(x)))
    """
       a  b  c
    0  a  6  9
    1  b  3  8
    """
    print(df.groupby(by="a", as_index=False).agg(lambda x: str(sum(x)) + "略略略"))
    """
       a     b     c
    0  a  6略略略  9略略略
    1  b  3略略略  8略略略
    """
    
    # 但是我们看到,pandas默认是对所有的列进行的聚合,可不可以指定某些列呢?
    # 答案是可以的,直接在groupby后面通过列表来指定即可,可以指定['b', 'c'],也可以指定[['b', 'c']]
    print(df.groupby(by="a")["b", "c"].agg(lambda x: sum(x)))
    """
       b  c
    a      
    a  6  9
    b  3  8
    """
    # 但是只选择一个列进行聚合,那么要写成[['b']],否则得到的是一个Series对象
    # 因为如果多个列,那么肯定是DataFrame,但是一个列,我们还想要DataFrame的话,那么就要写成[['b']]的形式
    print(df.groupby(by="a")[["b"]].agg(lambda x: sum(x)))
    """
       b  
    a     
    a  6  
    b  3  
    """
    
    # 除此之外我们还可以在agg里面指定要聚合的列
    print(df.groupby(by="a").agg({"b": "sum", "d": ' '.join}))
    """
       b      d
    a          
    a  6  我 一 条
    b  3    是 狗
    """
    # 你以为就这么完了,我们还可以对某列同时执行多个操作
    print(df.groupby(by="a").agg({"b": ["sum", lambda x: str(sum(x)) + "yoyoyo~"],
                                  "c": "mean",
                                  "d": [' '.join, lambda x: [_ + "旺旺 " for _ in x]]
                                  }
                                 )
          )
    """
        b               c      d                    
      sum <lambda_0> mean   join          <lambda_0>
    a                                               
    a   6   6yoyoyo~    3  我 一 条  [我旺旺 , 一旺旺 , 条旺旺 ]
    b   3   3yoyoyo~    4    是 狗        [是旺旺 , 狗旺旺 ]
    """
    # 我们看到有二级表头,b对应的有sum和<lambda_0>,命名是pandas内部的决策,如果是我们使用def定义的函数,那么就是函数名
    # 匿名函数,所以就叫lambda
    # c对应的有mean,d对应的有join和lambda
    
    
    # 最后再演示一下如何把二级表头变成一级表头,具体原理可以去网上搜索
    group = df.groupby(by="a").agg({"b": ["sum", lambda x: str(sum(x)) + "yoyoyo~"],
                                  "c": "mean",
                                  "d": [' '.join, lambda x: [_ + "旺旺 " for _ in x]]
                                  }
                                 )
    columns1 = group.columns.get_level_values(0)
    columns2 = group.columns.get_level_values(1)
    group.columns = columns1 + "_" + columns2
    print(group)
    """
       b_sum b_<lambda_0>  c_mean d_join        d_<lambda_0>
    a                                                       
    a      6     6yoyoyo~       3  我 一 条  [我旺旺 , 一旺旺 , 条旺旺 ]
    b      3     3yoyoyo~       4    是 狗        [是旺旺 , 狗旺旺 ]
    """
    

    transform

    import pandas as pd
    
    df = pd.DataFrame({
        "x": ['a', 'b', 'a', 'a', 'b'],
        "y": [1, 2, 3, 2, 1],
        "z": [3, 1, 5, 1, 7],
    })
    
    # transform依旧依赖于groupby
    print(df.groupby(by=["x"], as_index=False).agg("sum"))
    """
       x  y  z
    0  a  6  9
    1  b  3  8
    """
    print(df.groupby(by=["x"], as_index=False).transform("sum"))
    """
       y  z
    0  6  9
    1  3  8
    2  6  9
    3  6  9
    4  3  8
    """
    # 我们看到如果是groupby后面直接通过agg进行聚合的话,那么行的数量会变少,因为聚合了嘛。而且by指定的列就不会有重复了
    # 但如果是通过transform的话,那么行是不会减少的,原来是多少行结果还是多少行,并且自动把by指定的列给去掉了。
    # 可以这么理解,我们用普通的聚合作为比喻:
    """
    如果是agg("sum")的话,by="x"这一列只有a和b,说明原来的"x"这个列只有a和b两种数据。可能数量很多,但种类只有a和b两种
    
    聚合之后,a对应y中的6,对应z中的9
    那么transform("sum")就相当于把原来x列中所有元素为a的,对应的y中的元素全部换成6,对应的z中的元素全部换成9
    
    聚合之后,b对应y中的3,对应z中的8
    那么transform("sum")就相当于把原来x列中所有元素为b的,对应的y中的元素全部换成3,对应的z中的元素全部换成8
    
    可能逻辑有点不好说,那么再来举个例子
    
    x y
    a 2
    b 1
    a 3
    
    agg("sum"):
        x y 
        a 5
        b 1
    transform("sum")
        y
        5
        1
        5
    
    因为聚合之后,a对应5,b对应1
    那么就把原来a对应的y中的元素全部换成5,b对应的y中元素全部换成1
    """
    
    # 如果想要指定某些列该怎么办呢?显然和刚才介绍的一样
    print(df.groupby(by=["x"], as_index=False)[["y"]].transform("sum"))
    """
       y
    0  6
    1  3
    2  6
    3  6
    4  3
    """
    # 并且如果我们使用transform之后还需要by后面指定的列、这里是"x",那么直接手动添加即可,因为顺序是不变的,假设transform之后的结果赋值给变量trans,那么直接通过trans["x"] = df["x"]就行了。
    # 到此结束了,可以看到transform的操作就没有agg那么丰富了
    

    pivot_table

    import pandas as pd
    
    df = pd.DataFrame({
        "x": ['a', 'b', 'a', 'a', 'b'],
        "y": [1, 2, 3, 2, 1],
        "z": [3, 1, 5, 1, 7],
    })
    # 通过pivot_table,这个方法是pd下面的
    # 指定df、index(相当于groupby中的参数by)、values(要聚合的列)、aggfunc(聚合函数)得到结果和groupby是一样的
    # 如果不想作为索引,需要再手动调用reset_index()
    print(pd.pivot_table(df, index=["x"], values=["y", "z"], aggfunc="sum"))
    """
       y  z
    x      
    a  6  9
    b  3  8
    """
    
    # aggfunc里面也可以指定多个操作
    print(pd.pivot_table(df, index="x", values=["y"], aggfunc=["sum", "count"]))
    """
      sum count
        y     y
    x          
    a   6     3
    b   3     2
    """
    
    # 不指定values,那么则是对所有的列进行聚合
    print(pd.pivot_table(df, index=["x"], aggfunc="sum"))
    """
       y  z
    x      
    a  6  9
    b  3  8
    """
    
    # 也可以对不同的列使用不同的聚合函数
    print(pd.pivot_table(df, index=["x"], aggfunc={"y": ["count", "sum"], "z": "sum"}))
    """
          y       z
      count sum sum
    x              
    a     3   6   9
    b     2   3   8
    """
    
    # 我们看到可以通过pivot_table实现groupby的agg操作
    # 但是pivot_table支持的操作并不止这些,里面还有其它参数,比如:columns,这是一个很重要的参数
    # 具体怎么使用可以网上搜索,我们这里只用它实现groupby的效果
    
  • 相关阅读:
    安卓linux真机调试
    Java开发必装的IntelliJ IDEA插件
    在switch中的case语句中声明变量会被提前
    PostgresSQL 数组包含@>
    SQL 增加列、修改列、删除列
    ConcurrentHashMap 的实现原理
    Apache——DBUtils框架ResultSetHandler接口使用
    [转](不理想)Ubuntu下更改主显示器
    [问题记录]Java关于可变参数重载问题的测试
    使用openssl生成双向加密证书(转)
  • 原文地址:https://www.cnblogs.com/traditional/p/12387565.html
Copyright © 2020-2023  润新知