相关文章推荐
稳重的佛珠  ·  JAR will be empty - ...·  6 月前    · 
豪情万千的刺猬  ·  2024年宝山区义务教育阶段学校校区范围与招 ...·  6 月前    · 
酒量小的人字拖  ·  阴阳元尊_百度百科·  7 月前    · 
销魂的开心果  ·  PRML勘误表_prml 错误表-CSDN博客·  8 月前    · 
酒量大的仙人掌  ·  2023年射击世锦赛:李越宏以刷新世界纪录成 ...·  8 月前    · 
Code  ›  【Python】数据分析.pandas.数据的分组、聚合_骑着蜗牛ひ追导弹'的博客
数据分析 大数据 星巴克 聚合数据
https://blog.csdn.net/qq_45797116/article/details/106650717
爱旅游的红茶
2 年前
  • 数据分析.pandas.数据的分组、聚合
    • 一、分组---groupby()
    • 二、DataFrameGroupBy对象
    • 三、聚合
      • 3.1 简单直接聚合
      • 3.2 使用agg方法聚合数据
        • 3.2.1 自定义函数
        • 3.2.2 实现对分组后的数据进行统计
      • 3.3 使用apply方法聚合数据
      • 3.4 使用transform方法聚合数据
    • 四、星巴克案例扩展
    • 五、911紧急拨号案例扩展

    数据分析.pandas.数据的分组、聚合

    对数据进行整体性的聚合运算以及分组操作也是数据分析的重要内容。
    通过数据的聚合与分组,我们能更容易的发现隐藏在数据中的规律。下面我们根据星巴克的案例来进行学习~

    一、分组—groupby()

    这里所用到的分组方法与数据库里所学到的分组基本一样,可以按照某一列或者是某几列进行分组。

    以下是groupby()函数的源码:
    在这里插入图片描述 在这里插入图片描述
    当然,它的底层还是有另一层源码的,这里不再深入,主要就是详细的如何分组,大家可以去看一下~但通过这上面的两端,我们不难发现groupby()方法返回的是一个Series类型的值,下面我们会解释。

    下面结合案例来进行解释
    基本需求:得到每个国家的星巴克店的数量

    第一步:分组

    import numpy as np
    import pandas as pd
    file_path = "starbucks/directory.csv"
    df = pd.read_csv(file_path)
    # print(df.head(1))
    # print(df.info())
    #按照国家来分类
    grouped = df.groupby(by="Country")
    print(grouped)
    #这里的grouped得到的是一个DataFrameGroupBy对象,可迭代
    

    二、DataFrameGroupBy对象

    经过groupby()分组后得到的是一个DataFrameGroupBy对象,不可以直接显示具体数据,只能显示出在内存中的内存地址。

    对于该对象具体数据,我们可以通过迭代来进行查看:

    # 可以进行遍历
    for i in grouped:
         print(i)
         print("*"*100) #返回一个两个元素的元组,第一个是国家(Country),第二个是该国家下的所有数据,类型是dataframe
    # ('AE',          Brand  Store Number  ... Longitude Latitude
    # 1    Starbucks  22331-212325  ...     55.47    25.42
    # 2    Starbucks  47089-256771  ...     55.47    25.39
    # 3    Starbucks  22126-218024  ...     54.38    24.48
    # 4    Starbucks  17127-178586  ...     54.54    24.51
    # 5    Starbucks  17688-182164  ...     54.49    24.40
    # ..         ...           ...  ...       ...      ...
    # 140  Starbucks   34253-62541  ...     55.38    25.33
    # 141  Starbucks   1359-138434  ...     55.38    25.32
    # 142  Starbucks   34259-54260  ...     55.37    25.30
    # 143  Starbucks   34217-27108  ...     55.48    25.30
    # 144  Starbucks  22697-223524  ...     55.54    25.53
    # [144 rows x 13 columns])
     

    以上是按照国家分组后每个国家的星巴克情况(由于数据较大,只截取了国家为‘AE’的,中间数据也有部分省略)

    我们可以看到,该对象返回一个两个元素的元组,第一个是国家(Country),第二个是该国家下的所有数据,类型是dataframe。

    3.1 简单直接聚合

    所谓聚合,就是执行多个值变成一个值的操作。而在Python中,就是将一个矢量(数组)变成标量。在Python中主要有如图所示的几中聚合方法。在这里插入图片描述

    print('订单详情表分组后前5组的均值为:\n',detailgroup.mean().head())
    #订单详情表分组后前5组的均值为:
               counts  amounts
    order_id                 
    1002      1.0000   32.000
    1003      1.2500   30.125
    1004      1.0625   43.875
    1008      1.0000   63.000
    1011      1.0000   57.700
    print('订单详情表分组后前5组的标准差为:\n',detailgroup.std().head())
    #订单详情表分组后前5组的标准差为:
                counts    amounts
    order_id                    
    1002      0.00000  16.000000
    1003      0.46291  21.383822
    1004      0.25000  31.195886
    1008      0.00000  64.880660
    1011      0.00000  50.077828
    print('订单详情表分组后前5组的每组大小:\n',detailgroup.size().head())
    #订单详情表分组后前5组的每组大小:
     order_id
    1002     7
    1003     8
    1004    16
    1008     5
    1011    10
    dtype: int64
    

    第二步:调用聚合函数计算

    # 可以调用聚合函数
    print(grouped.count()) #会将每一列按照国家来进行进行统计
    #          Brand  Store Number  Store Name  ...  Timezone  Longitude  Latitude
    # Country                                   ...
    # AD           1             1           1  ...         1          1         1
    # AE         144           144         144  ...       144        144       144
    # AR         108           108         108  ...       108        108       108
    # AT          18            18          18  ...        18         18        18
    # AU          22            22          22  ...        22         22        22
    #         ...           ...         ...  ...       ...        ...       ...
    # TT           3             3           3  ...         3          3         3
    # TW         394           394         394  ...       394        394       394
    # US       13608         13608       13608  ...     13608      13608     13608
    # VN          25            25          25  ...        25         25        25
    # ZA           3             3           3  ...         3          3         3
    # [73 rows x 12 columns]
    print(grouped["Brand"].count()) #也可以对其中的所需要的一列进行统计
    # AD        1
    # AE      144
    # AR      108
    # AT       18
    # AU       22
    #       ...
    # TT        3
    # TW      394
    # US    13608
    # VN       25
    # ZA        3
    # Name: Brand, Length: 73, dtype: int64
    

    3.2 使用agg方法聚合数据

    agg、aggregate方法都可以对每个分组应用某个函数,也可以直接对dataframe进行函数操作。
    实际操作过程中两种方法作用相同

    DataFrame.agg(func,axis=0,*args,**kwargs)
    DataFrame.aggregate(func,axis=0,*args,**kwargs)
    

    可以使用agg函数求出对应的统计量;也可以根据要求,对于某个字段做单独的处理,例如对counts字段进行求和,对amounts字段进行求均值,但此时需要以字典的形式,将字段名作为key,函数作为value传入;同时还可以对不同字段的不同数目进行统计,当不唯一时只需要将字典对应的value转换为列表即可。
    在这里插入图片描述

    3.2.1 自定义函数

    注意在agg中可以使用numpy库中的函数(np.mean、np.median、np.prod、np.sum、np.std、np.var),但是在自定义函数中使用此类函数时,若计算的是单个序列,则无法得到预期结果,需为多列数据同时计算。
    在这里插入图片描述
    返回顶部

    3.2.2 实现对分组后的数据进行统计

    3.3 使用apply方法聚合数据

    与agg方法相比较,agg方法传入的参数只能够作用于整个DataFrame或者Series,并且apply方法无法像agg方法一样对不同的字段应用不同的函数来获取不同的结果。

    DataFrame.apply(func,axis=0,broadcast=False,raw=False,reduce=None,arg=(),**kwds)
    
    参数名称说明
    func接收functions。代表应用于每行或每列的函数
    axis接收0或1,代表操作的轴向
    broadcast接收boolean,代表是否进行广播,默认为False
    raw接收boolean,表示是否直接将ndarray对象传递给参数,默认为False
    reduce接收boolean或None,表示返回的格式

    3.4 使用transform方法聚合数据

    transform方法能够对整个DataFrame的所有元素进行操作

    在这里插入图片描述
    在这里介绍一下使用lambda表达式定义函数:
    1.lambda表达式定义函数是比较特殊一种函数定义方式,该函数是中匿名函数,也就是该函数没有函数名。使用该中函数会返回一个值,调用时直接使用该函数的值。
    2.在lambda表达式中不能够使用print语句
    3.在lambda表达式中不能够使用其他语句

    在这里插入图片描述

    groupby对象的函数
    ----- apply
    在不同分组上应用‘func’函数,然后将结果组合起来。
    ----- agg/aggregate
    聚合(agg/aggregate)在特定轴(列)上应用一或多个操作(函数)
    ----- transform
    调用函数在每个分组上产生一个与原df相同索引的DataFrame,整体返回与原来对象拥有相同索引且
    已填充了转换后的值的DataFrame

    四、星巴克案例扩展

    需求:比较中国和美国的星巴克店数

    在上面的基础上,我们来获取中国和美国的星巴克店的数量
    country_count = grouped["Brand"].count()
    print(country_count["US"]) //美国
    print(country_count["CN"]
    
    
    
    
        
    ) //中国
    

    在这里插入图片描述
    需求:具体了解到中国的每一个省份的星巴克店的数量

    china_data = df[df["Country"]=="CN"] 
    #注意这里在查找时是作为条件,应当为bool类型
    grouped = china_data.groupby(by="State/Province").count()["Brand"]
    print(grouped) #数字代表中国的省份编码
    # State/Province
    # 11    236
    # 12     58
    # 13     24
    # 14      8
    # 15      8
    # 21     57
    # 22     13
    # 23     16
    # 31    551
    # 32    354
    # 33    315
    # 34     26
    # 35     75
    # 36     13
    # 37     75
    # 41     21
    # 42     76
    # 43     35
    # 44    333
    # 45     21
    # 46     16
    # 50     41
    # 51    104
    # 52      9
    # 53     24
    # 61     42
    # 62      3
    # 63      3
    # 64      2
    # 91    162
    # 92     13
    # Name: Brand, dtype: int64
    

    需求:按照多个条件进行分组,同时按照国家和省份分组
    这样会显示出每个国家的每个地区的数量情况,更加直观~

    #同时按照国家和省份分组,就会有两个索引,返回的是Series
    grouped = df["Brand"].groupby(by=[df["Country"],df["State/Province"]]).count()
    print(grouped)
    # Country  State/Province
    # AD       7                  1
    # AE       AJ                 2
    #          AZ                48
    #          DU                82
    #          FU                 2
    #                            ..
    # US       WV                25
    #          WY                23
    # VN       HN                 6
    #          SG                19
    # ZA       GT                 3
    # Name: Brand, Length: 545, dtype: int64
    

    补充:
    若想返回的值是DataFrame类型,可以再案列名查找时多添加一个"[]"

    grouped1 = df[["Brand"]].groupby(by=[df["Country"],df["State/Province"]]).count()
    print(grouped1,type(grouped1))
    print("*"*100)
    grouped2 = df.groupby(by=[df["Country"],df["State/Province"]])[["Brand"]].count()
    print(grouped2,type(grouped2))
    print("*"*100)
    grouped3 = df.groupby(by=[df["Country"],df["State/Province"]]).count()[["Brand"]]
    print(grouped3,type(grouped3))
    #以上的三种方式结果均为下表
    #                         Brand
    # Country State/Province
    # AD      7                   1
    # AE      AJ                  2
    #         AZ                 48
    #         DU                 82
    #         FU                  2
    #                        ...
    # US      WV                 25
    #         WY                 23
    # VN      HN                  6
    #         SG                 19
    # ZA      GT                  3
    # [545 rows x 1 columns] <class 'pandas.core.frame.DataFrame'>
    

    需求:使用matplotlib呈现出店铺总数排名前十的国家

    #使用matplotlib呈现出店铺总数排名前十的国家
    import numpy as np
    import pandas as pd
    from matplotlib import pyplot as plt
    from matplotlib import font_manager
    #设置字体
    #设置字体
    my_font=font_manager.FontProperties(fname="C:\Windows\Fonts\STXINGKA.TTF",size=18)
    #准备数据
    file_path = "starbucks/directory.csv"
    df = pd.read_csv(file_path)
    data = df.groupby(by="Country").count()["Brand"].sort_values(ascending=False)[:10]
    x = data.index
    y = data.values
    #设置图形大小
    plt.figure(figsize=(20,8),dpi=80)
    plt.bar(range(len(x)),y)
    plt.xticks(range(len(x)),x)
    #添加信息
    plt.xlabel("国家",fontproperties=my_font)
    plt.ylabel("该国星巴克店铺数",fontproperties=my_font)
    plt.title("星巴克店铺总数排名前十的国家",fontproperties=my_font)
    plt.show()
    

    在这里插入图片描述
    需求:中国星巴克数排名前25的城市店铺总数

    import numpy as np
    import pandas as pd
    from matplotlib import pyplot as plt
    from matplotlib import font_manager
    #设置字体
    #设置字体
    my_font=font_manager.FontProperties(fname="C:\Windows\Fonts\STXINGKA.TTF",size=18)
    #准备数据
    file_path = "starbucks/directory.csv"
    df = pd.read_csv(file_path)
    df = df[df["Country"]=="CN"]
    data = df.groupby(by="City").count()["Brand"].sort_values(ascending=False)[:25]
    x = data.index
    y = data.values
    #设置图形大小
    plt.figure(figsize=(20,8),dpi=80)
    plt.bar(range(len(x)),y,width=0.3)
    plt.xticks(range(len(x)),x,fontproperties=my_font)
    #添加信息
    plt.xlabel("城市",fontproperties=my_font)
    plt.ylabel("该城市星巴克店铺数",fontproperties=my_font)
    plt.title("中国星巴数排名前25的城市克店铺总",fontproperties=my_font)
    #绘制网格
    plt.grid()
    plt.show()
    

    在这里插入图片描述
    通过绘制图形显示直接明了,但是这里还有不足之处,就是x轴太密集,不便于观察,接下来我们进行操作,使用横向的条形图。(
    关于条形图的绘制可参考本人之前的文章)

    x = data.index
    y = data.values
    #设置图形大小
    plt.figure(figsize=(20,8),dpi=80)
    plt.barh(range(len(x)),y,height=0.3)
    plt.yticks(range(len(x)),x,fontproperties=my_font)
    #添加信息
    plt.ylabel("城市",fontproperties=my_font)
    plt.xlabel("该城市星巴克店铺数",fontproperties=my_font)
    plt.title("中国星巴数排名前25的城市克店铺总数",fontproperties=my_font)
    

    五、911紧急拨号案例扩展

    需求:计算911紧急拨号不同类型的次数
    在这里插入图片描述
    根据已经获取到的数据,我们可以从中发现,具体的分类是在title列下字符串的前半段。至此,我们可以明确目标:

    1.获取分号之前的字符串 ----- 按照“:”切割
    2.统计 ----- sum()、count()

    方法一:在原有数据基础上,直接分类统计
    思路:首先,按照“:”分割字符串并将结果转化为list;接着,遍历list,将第i个元素中的第一个子元素取出,就得到了每个元素的分类,再用set()去重,最后转为list得到所有分类类型的列表;然后,我们就该统计,按照常理,既然有了所有分类,之前又得到了分割后具有分类的列表,那么直接去遍历,对应分类计数即可。在执行过程中会有两种方式:
    1.逐行遍历赋值
    每一行都去和分类比较,在对应的分类下计数
    这种方式理论可行,但在实际的操作执行过程中很耗时间。
    2.分类赋值
    按照找出的分类,按照分类赋值
    其中涉及contains()函数,它可以迅速返回目标的布尔值,借助布尔值实现直接分类赋值。
    在统计时我们还要创建一组全为零的dataframe,遍历计数是需要用到的。

    import numpy as np
    import pandas as pd
    from matplotlib import pyplot as plt
    from matplotlib import font_manager
    #设置中文
    my_font = font_manager.FontProperties(fname="C:\Windows\Fonts\STXINGKA.TTF",size=18)
    #读取csv文件
    file_path = "911-calls/911.csv"
    df = pd.read_csv(file_path)
    #获取分类
    temp_list = df["title"].str.split(":").tolist()
    #分类在title字段中,这里将以:切分字符串并转化为list,每个元素类似于['EMS', ' SUBJECT IN PAIN']
    cate_list = list(set(i[0] for i in temp_list))
    #先遍历list,将第i个元素中的第一个子元素取出,就得到了每个元素的分类,再用set()去重,最后转为list得到分类的列表
    print(cate_list) #['Traffic', 'Fire', 'EMS']
    #构造全为0的数组
    zeros_df = pd.DataFrame(np.zeros((df.shape[0],len(cate_list))),columns=cate_list)
    #法一,遍历分类,为该分类的赋值
    for cate in cate_list:
        zeros_df[cate][df["title"].str.contains(cate)] = 1
    print(zeros_df)
    #法二,逐行遍历赋值
    # for i in range(df.shape[0]):
    #     zeros_df.loc[i,temp_list[i][0]] = 1
    # print(zeros_df)
    sum_ret = zeros_df.sum(axis=0)
    print(sum_ret)
     

    方法二:在原有数据基础上,再设置一列为分类,进行对该列的统计
    思路:首先,按照“:”分割字符串并将结果转化为list;接着,遍历list,将第i个元素中的第一个子元素取出,定义为新的一列;最后,直接分组统计分类一列即可。

    import numpy as np
    import pandas as pd
    from matplotlib import pyplot as plt
    from matplotlib import font_manager
    #设置中文
    my_font = font_manager.FontProperties(fname="C:\Windows\Fonts\STXINGKA.TTF",size=18)
    #读取csv文件
    file_path = "911-calls/911.csv"
    df = pd.read_csv(file_path)
    #获取分类
    temp_list = df["title"].str.split(":").tolist()
    #分类在title字段中,这里将以:切分字符串并转化为list,每个元素类似于['EMS', ' SUBJECT IN PAIN']
    cate_list = [i[0] for i in temp_list]
    #先遍历list,获取出第i个元素中的第一个子元素
    cate_df = pd.DataFrame(np.array(cate_list).reshape((df.shape[0]),1))
    df["cate"] = cate_df #添加新的一列分类
    print(df.groupby(by="cate").count()["title"])
                        Python----数据分析-pandas.数据的分组、聚合对数据进行整体性的聚合运算以及分组操作也是数据分析的重要内容。通过数据的聚合与分组,我们能更容易的发现隐藏在数据中的规律。下面我们根据星巴克的案例来进行学习~......
    分组聚合的原理一般分为拆分-应用-合并。( )
    只要使用groupby()方法分组就会产生一个DataFrameGroupby对象。( )
    使用agg()方法进行聚合运算会对产生的标量值进行广播。( )
    使用transform()方法进行聚合运算,其结果可以保持与原数据形状相同。( )
    apply()方法可以使用广播功能。( )
    下列选项中,关于groupby()方法说法不正确的是。( )
    分组键可以是列表或数组,但长度不需要与待分组轴的长度相同
    可以通过DataFrame中的列名的值进行分组
    可以使用函数进行分组
    可使用series或字典分组
    下列选项中,关于agg()方法使用不正确是。( )
    agg()方法中func参数只能传入一个函数
    agg()方法中func参数可以传入多个函数
    agg()方法中func参数可以传入自定义函数
    agg()方法不能对产生的标量值进行广播
      其实这种数据分组与SQL中的Group by语句的功能是一样的。
     实际上,我们可以把 groupby 理解成一个分割(split),应用(apply),组合(combine)的过程
      一个经典分割-应用-组合操作如下图所示,其中应用的是一个求和函数.
    分割: 将 DataFrame按照指定的键分割成若干组
    应用: 对每个组应用函数, 通常是累计,转换或过滤函数
    组合: 将每一组的结果合并成一个输出组
    数据分组
      在数据处理中, 我们经常需要把某些特征的共同值进行累计分析
    在SQL中我们经常使用 GROUP BY 将某个字段,按不同的取值进行分组, 在pandas中也有groupby函数
    分组之后,每组都会有至少1条数据, 将这些数据进一步处理返回单个值的过程就是聚合,比如 分组之后计算算术平均值, 或者分组之后计算频数,都属于聚合
    				
    数据聚合,一般都是指对分组中的数据执行某些操作,比如求平均值、求最大值等,并且操作后得到一个结果集,这些实现聚合的操作称为聚合方法。Pandas中提供了用做聚合操作的agg()方法。 一、使用内置统计方法聚合数据        前面已经介绍过Pandas的统计方法,比如用于获取最大值和最小值的max()和min(),这些方法常用于简单地聚合分组中的数据。       假设现在我们
    Python报错:‘unicodeescape‘ codec can‘t decode bytes in position 2-3: truncated \UXXXXXXXX escape 45993
 
推荐文章
稳重的佛珠  ·  JAR will be empty - no content was marked for inclusion!_kq的技术博客_51CTO博客
6 月前
豪情万千的刺猬  ·  2024年宝山区义务教育阶段学校校区范围与招生计划(初中)
6 月前
酒量小的人字拖  ·  阴阳元尊_百度百科
7 月前
销魂的开心果  ·  PRML勘误表_prml 错误表-CSDN博客
8 月前
酒量大的仙人掌  ·  2023年射击世锦赛:李越宏以刷新世界纪录成绩斩获男子25米手枪速射冠军,为中国射击队锁定巴黎奥运会席位
8 月前
今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
删除内容请联系邮箱 2879853325@qq.com
Code - 代码工具平台
© 2024 ~ 沪ICP备11025650号