python 数据分析(六)astype(‘category‘)按类别分组 + 分组聚合操作 + 透视表 + 交叉表 + excel表的数据处理一、按照类别单独分类astype()二、时间操作三、分组

本文详细介绍了如何使用pandas的astype方法按类别分类,时间序列处理的to_datetime和Series.dt,以及分组、聚合(agg)、透视表和crosstab的高效应用,包括离差标准化和部门员工统计。

文章目录

  • 一、按照类别单独分类astype()

      1. astype()用法

  • 二、时间操作

      1. 第一种:直接利用to_datetime()

      1. 第二种:Series.dt

  • 三、分组聚合操作

      1. 分组

      • (1)groupby()方法

      1. 聚合

      • (1)agg()方法

        • ① 使用方法1

        • ② 使用方法2

        • ③ 使用方法3

        • ④ 使用方法4

      • (2)在分组的基础上进行聚合操作

      • (3)apply()方法

      • (4)transform()方法

        • ① 对于离差标准化

  • 四、透视表

  • 五、crosstab 函数创建交叉表

  • 六、excel表的数据处理

      1. 工号与名字一致重复(去重)

      1. 员工平均工作年限

      1. 任职最久的3位

      1. 员工总体流失率

      1. 各部门有多少员工

一、按照类别单独分类astype()


按照普通的mean来求菜品的均价无法计算(中间可能会有重复的菜品); 但按照类别对菜品进行分类获取的菜品是唯一的,这就用到了astype()方法并配合category(类别)来完成 普通求法:

    import pandas
    detail = pandas.read_excel('detail.xlsx')
    print(detail.loc[:,['counts','amounts']].describe())

在这里插入图片描述 获得的count会有重复,这就会用到astype


1. astype()用法


    detail['dishes_name'] = detail['dishes_name'].astype('category')
    print(detail['dishes_name'].describe())
    print(detail['dishes_name'])

在这里插入图片描述在这里插入图片描述


二、时间操作


将本身的数据类型转换成符合条件的时间日期型,方便数据操作


1. 第一种:直接利用to_datetime()


    import pandas
    
    detail = pandas.read_excel('detail.xlsx')
    detail['place_order_time'] = pandas.to_datetime(detail['place_order_time'])
    year = [i.year for i in detail['place_order_time']]

在这里插入图片描述


2. 第二种:Series.dt


序列的.dt方法其实就是datatime方法的转换

    print(detail['place_order_time'].dt.year)

在这里插入图片描述


三、分组聚合操作


1. 分组


(1)groupby()方法


groupby参数:

    def groupby(self, by=None, axis=0, level=None, as_index=True, sort=True,group_keys=True, squeeze=False, **kwargs)

在这里插入图片描述


分组获取指定列对象

    result = detail[['order_id','counts','amounts']].groupby(by='order_id')
    print(result) # <pandas.core.groupby.DataFrameGroupBy object at 0x0000000005BCAEB8>

在这里插入图片描述 获取的是DataFrameGroupBy 对象

    print(result['order_id'])#SeriesGroupBy

但对于DataFrameGroupBy取出的就是SeriesGroupBy对象

我们可以对分组后的对象进行一些操作:如均值

    result = detail.groupby(by='order_id')
    print(result[['counts','amounts']].mean().head())

在这里插入图片描述 亦可以对分组后的对象进行一些聚合操作

    ## size 分组后每组的条数order_id
    print(result.size())
    
    ## sum,分组后:每个订单点了多少份菜,消费总额度
    print(result.sum())

在这里插入图片描述说明:可以进行分组,分组后的所有列只能使用一种聚合函数操作 注意:如果想让不同的列进行不同的聚合操作,需要写两次代码


2. 聚合


(1)agg()方法


    DataFrame.agg(func, axis=0, *args, **kwargs)
    # func是一个函数,如果接多个函数,需要使用列表将多个函数名封装起来,可以使用我们自己定义的也可以使用聚合函数
  • agg,aggregate 方法都支持对每个分组应用某函数,包括 Python 内置函数或自定义函数。 同时这两个方法能够也能够直接对 DataFrame 进行函数应用操作。

  • 在正常使用过程中,agg 函数和 aggregate 函数对 DataFrame 对象操作时功能几乎完全相 同,因此只需要掌握其中一个函数即可。

  • 它们的参数说明如下表 在这里插入图片描述

以我们之前的所学无法求不同列的均值,和等聚合操作;但利用agg方法我们可以来做个尝试

  • 求不同列的和 [code] result1 = detail[['counts','amounts']].agg(numpy.sum)

    print(result1)

![在这里插入图片描述](https://img-blog.csdnimg.cn/20191121202831274.png?x-oss-
process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xhbmdkZWk=,size_16,color_FFFFFF,t_70)  
**说明:agg函数解决了让不同的列可以进行不同的聚合操作**

* * *

####  ① 使用方法1

* * *

  * 对counts和amounts进行均值、求和操作 
[code]     result2 = detail[['counts','amounts']].agg([numpy.sum,numpy.mean])

    print(result2)

在这里插入图片描述


② 使用方法2


  • 对counts进行求和操作,对amounts进行均值操作 [code] result3 = detail.agg({'counts':numpy.sum,'amounts':numpy.mean})

    print(result3)

![在这里插入图片描述](https://img-blog.csdnimg.cn/20191121203852902.png)

* * *

####  ③ 使用方法3

* * *

  * 对一个列进行多个聚合操作, 
[code]     result4 =
detail.agg({'counts':numpy.sum,'amounts':[numpy.sum,numpy.mean]})

    print(result4)

在这里插入图片描述


④ 使用方法4


  • 实现将自定义函数作为聚合函数统计函数

    def double_sum(data):
        return numpy.sum(data)*2
    
    result5 = detail.agg({'counts':double_sum})
    print(result5)

在这里插入图片描述


(2)在分组的基础上进行聚合操作


即DataFrameGroupBy.聚合操作

    result6 = detail[['order_id','counts','amounts']].groupby(by='order_id')
    group_agg_result = result6.agg({'counts':numpy.sum,'amounts':[numpy.sum,numpy.mean]})
    print("使用order_id进行分组后的DataFrameGroupBy进行聚合操作:\n",group_agg_result)

在这里插入图片描述


(3)apply()方法


注意:agg与apply的区别: 主要区别在于

  • apply是对整个表格中的数据进行聚合操作

  • 而agg方法可以让不同的字段应用不同的聚合函数

相同之处就是:

  • 都可以对分组后的数据进行聚合操作

    DataFrame.apply(func, axis=0, broadcast=False, raw=False, reduce=None, args=(), **kwds)

在这里插入图片描述


apply仅支持对某些列或所有数据进行聚合操作,但满足不了不同的列应用不同的聚合操作

    result7 = detail[['counts','amounts']].apply(numpy.mean)
    print("使用apply对这两个字段进行聚合操作:\n",result7)

在这里插入图片描述 因为参数是func,亦可以完成多个聚合操作 在这里插入图片描述 在分组后也可以使用apply进行聚合操作 在这里插入图片描述


(4)transform()方法


  • transform 方法能够对整个 DataFrame 的所有元素进行操作。且 transform 方法只有一个 参数“func”,表示对 DataFrame 操作的函数。

  • 同时 transform 方法还能够对 DataFrame 分组后的对象 GroupBy 进行操作,可以实现组 内离差标准化等操作。

  • 若在计算离差标准化的时候结果中有 NaN,这是由于根据离差标准化公式,最大值和 最小值相同的情况下分母是 0。而分母为 0 的数在 Python 中表示为 NaN。

    def transform(self, func, *args, **kwargs)

func表名可以传入函数对其聚合操作,自定义函数进行离差标准化操作 在这里插入图片描述


① 对于离差标准化


agg/apply/transform都可以用来做离差标准化;因为参数中都有func,都可以自定义函数

    counts_min = detail['counts'].min()
    counts_max = detail['counts'].max()
    # ## 用result6报错是因为分组后取counts是一组一组的,不是一个一个的数据
    
    print("对counts进行离差标准化",detail['counts'].transform(lambda x:(x-counts_min)/(counts_max-counts_min)))
    print("对counts进行离差标准化",detail['counts'].apply(lambda x:(x-counts_min)/(counts_max-counts_min)))
    print("对counts进行离差标准化",detail['counts'].agg(lambda x:(x-counts_min)/(counts_max-counts_min)))

在这里插入图片描述 注意:不能用分组后的数据来进行离差标准化;分组后取counts是一组一组的,不是一个一个的数据

通过离差标准化可以计算方差或标准差 衡量数据离散程度可以使用方差或标准差

    amounts_min = detail['amounts'].min()
    amounts_max = detail['amounts'].max()
    print('菜品价格的标准差:',detail['amounts'].std())
    detail['amounts_licha']= (detail['amounts'] - amounts_min)/(amounts_max-amounts_min)
    print('菜品价格的离差标准化:',detail['amounts_licha'].std())

在这里插入图片描述 不使用离差标准化会因为单位不同等原因造成方差的结果很大,对实际不符


四、透视表


利用 pivot_table 函数可以实现透视表,pivot_table()函数的常用参数及其使用格式如下

    def pivot_table(data, values=None, index=None, columns=None, aggfunc='mean',fill_value=None, margins=False, dropna=True,margins_name='All')

在这里插入图片描述

  • pivot_table自带聚合函数mean操作(默认的)在不特殊指定聚合函数 aggfunc 时,会默认使用 numpy.mean 进行聚合运算,numpy.mean 会自动过滤掉非数值类型数据。可以通过指定 aggfunc 参数修改聚合函数。

  • index相当于分组;如下面对order_id分组;和 groupby 方法分组的时候相同,pivot_table 函数在创建透视表的时候分组键 index 可 以有多个

  • 通过设置 columns 参数可以指定列分组

  • 当全部数据列数很多时,若只想要显示某列,可以通过指定 values 参数来实现。

  • 当某些数据不存在时,会自动填充 NaN,因此可以指定 fill_value 参数,表示当存在缺 失值时,以指定数值进行填充

  • 可以更改 margins 参数,查看汇总数据。

    • *

    detail_pivot1 = pandas.pivot_table(detail[['order_id','counts','amounts']],index='order_id')
    print(detail_pivot1)

在这里插入图片描述 按order_id分组,并求均值

如果想要指定聚合函数aggfunc=’' aggfunc=’'内置是字符串可以直接写聚合函数,但最好用numpy.方法;可以提示,防止写错

    detail_pivot2 = pandas.pivot_table(detail[['order_id','counts','amounts']],index='order_id',aggfunc=numpy.sum)
    print(detail_pivot2)

在这里插入图片描述


五、crosstab 函数创建交叉表


交叉表是一种特殊的透视表,主要用于计算分组频率。利用 pandas 提供的 crosstab 函数 可以制作交叉表,crosstab 函数的常用参数和使用格式如下

    pandas.crosstab(index, columns, values=None, rownames=None, colnames=None, aggfunc=None, margins=False, dropna=True, normalize=False)

在这里插入图片描述由于交叉表是透视表的一种,其参数基本保持一致,不同之处在于 crosstab 函数中的 index,columns,values 填入的都是对应的从 Dataframe 中取出的某一列。


交叉表和透视表的index区别:交叉表index不能直接跟字段名‘order_id’,跟的是字段值detail[‘order_id’]

    result = pandas.crosstab(index=detail['order_id'],columns=detail['dishes_name'],values=detail['counts'],aggfunc=numpy.sum)  ## sum是把相同order_id的放在一行了
    print(result)

在这里插入图片描述 columns为对应列的所有数据作为交叉表的列,values是对应数量放在对应列下,aggfunc=numpy.sum是把分组order_id的所有内容加到一行


六、excel表的数据处理


1. 工号与名字一致重复(去重)


     def drop_duplicates(self, subset=None, keep='first', inplace=False)
    import pandas
    data = pandas.read_excel('英雄联盟员工信息表.xlsx')
    print("原始数据:",data.shape) # 原始数据: (22, 8)
    #1. 工号与名字一致重复
    # def drop_duplicates(self, subset=None, keep='first', inplace=False)
    data.drop_duplicates(subset=['工号','姓名'],inplace=True)
    print("去除重复员工后:",data.shape) # 去除重复员工后: (20, 8)

在这里插入图片描述注意:drop_duplicates默认是对这一行的所有数据进行比对,完全一样才会骑去重;我们可以通过subset=[’’,’’]来指定几个字段去重 inplace=False有返回值,不作用在原数据上;inplace=True无返回值,作用在原数据上


2. 员工平均工作年限


    print(data['工龄'].mean()) # 3.8

3. 任职最久的3位


对序列进行排序用sort_values

    def sort_values(self, by, axis=0, ascending=True, inplace=False,kind='quicksort', na_position='last')
    result_Sort = data[['姓名','工龄']].sort_values(by='工龄',ascending=False,inplace=False)
    print(result_Sort.head(3))

在这里插入图片描述 ascending有两个值:True和False,升序和降序 注意:若是之前的表格改变,而且排序后再将值赋给表格会报错,可能是行缺失,可能是排序后值不匹配;所以用inplace=False


4. 员工总体流失率


    mask = data['状态']=='离职'
    print(mask)
    print(type(mask))
    
    print("离职率:",data.iloc[mask.values,:].shape[0]/data.shape[0]) # 离职率: 0.3

mask.values为False的则不显示,True的显示。通过判断有多少行来求离职的,除以所有的,即为离职率 在这里插入图片描述对一个序列对象如果单纯的想获取值,可以使用values属性

    print(mask.values) # [ True False False  True False False False False False False False False True False  True False False False  True  True]

根据上面的代码我们可以利用Boolean值相加减来获得离职的人数,以此来求离职率

    print("离职率:",mask.values.sum()/data.shape[0]) # 离职率: 0.3

5. 各部门有多少员工


    print(data[['部门','姓名']].groupby(by='部门').count())

在这里插入图片描述

    print((data[['部门']].groupby(by='部门')).count())

这种方式取出为空,因为你没有索引让他列出值


<think>嗯,用户现在想了解如何在Python生成的数据透视中动态调整字段配置,特别是使用pandas、openpyxl和Excel的情况。之前已经给过个基于win32com的解决方案,但用户可能想用更跨平台的方法,或者更灵活地调整字段。 首先,用户的问题中提到动态调整字段配置,这可能包括添加、删除或修改行、列、值或筛选字段。需要结合引用中的内容,特别是引用[3]里的数据透视设置步骤,以及用户之前提到的使用pandas和openpyxl的需求。 先回顾之前的回答,用户可能已经了解如何用win32com创建透视,但现在想用pandas的pivot_table函数或者其他库如openpyxl来实现动态调整。不过pandas本身的透视生成后是静态数据,不像Excel对象那样可以动态修改。不过,用户可能需要的是在生成透视时动态配置字段,而不是在生成后修改。 引用[3]提到数据透视的创建步骤,比如拖拽字段到行、列、值区域,并设置统计方式。这在pandas中可以通过pd.pivot_table的参数来指定,比如index(行)、columns(列)、values(值),aggfunc(聚合函数)。所以动态调整可能意味着允许用户输入不同的字段作为参数,或者根据数据变化自动调整。 另外,用户提到使用openpyxl,可能需要将生成的透视写入Excel并保持某些动态特性。但openpyxl处理数据透视的能力有限,可能需要结合其他方法。引用中的代码示例使用win32com来操作Excel对象模型,但用户现在可能希望更轻量级或不依赖Excel的解决方案。 所以可能的解决方案是:在Python中使用pandas生成数据透视,根据不同的参数动态调整index、columns、values等,然后通过openpyxl将结果写入Excel。如果需要更高级的交互性,可能需要结合Excel文件模板,在模板中预设数据透视,然后通过openpyxl更新数据源,但这种方法可能无法动态修改字段配置,除非使用VBA或win32com。 另外,用户之前的问题中提到“动态调整数据透视的字段配置”,可能需要根据用户输入或配置文件来改变生成透视时的字段。例如,从配置文件读取哪些字段作为行、列、值,然后在代码中动态应用这些配置。 需要考虑如何将动态参数传递给pandas的pivot_table函数。例如,使用字典或JSON配置来指定每个字段的角色,然后在生成透视时解包这些参数。这可能涉及到如何处理多个行或列字段,因为pandas允许传入列。 此外,引用[2]提到了使用pandas进行分组和开窗操作,这可能与数据透视的动态配置有关联,比如在生成透视前对数据进行预处理,比如过滤、排序或计算新字段,这也会影响最终的透视结构。 可能的步骤是: 1. 读取数据源。 2. 根据动态配置参数(比如用户选择的字段)构建pivot_table的参数。 3. 生成数据透视。 4. 将结果写入Excel,可能需要使用openpyxl来格式化输出。 对于动态调整,可能需要允许用户通过配置文件、命令行参数或交互式输入来指定字段。例如,使用个JSON文件来定义行、列、值字段及聚合方式,然后在代码中读取该配置并生成对应的透视。 在openpyxl中写入数据透视的话,可能只是写入静态数据,而不是真正的Excel数据透视对象。如果需要真正的数据透视对象,可能需要使用xlsxwriter库,它支持创建数据透视。但xlsxwriter不能修改现有文件,所以可能需要先用pandas处理数据,再用xlsxwriter生成带有透视的新Excel文件。 或者,结合openpyxl和pandas,先生成Excel文件,然后在其中使用openpyxl的API创建数据透视,但openpyxl的数据透视支持可能有限,可能需要更底层的操作。 综上,可能的解决方案是使用pandas的pivot_table函数动态生成数据透视的数据,然后使用xlsxwriter或openpyxl将结果写入Excel,并根据需要配置数据透视字段。或者,继续使用win32com来操作Excel应用,实现动态调整,但这样依赖Windows和Excel。 现在需要将这些思路整理成个清晰的步骤,并给出代码示例,说明如何动态配置字段,比如通过函数参数传递行、列、值字段,以及如何处理不同的聚合函数。同时,结合用户提供的引用内容,特别是引用[3]中的数据透视配置步骤,将其转化为pandas代码。</think>我将为您详细讲解如何在Python中动态调整数据透视的字段配置,提供种主流实现方式: ### 、Pandas原生动态配置方案 ```python def dynamic_pivot(df, index_cols, column_cols, value_cols, aggfunc='sum'): """动态生成数据透视""" return pd.pivot_table(df, index=index_cols, columns=column_cols, values=value_cols, aggfunc=aggfunc) # 示例配置参数 config = { "index": ["区域", "产品线"], "columns": ["季度"], "values": ["销售额", "库存量"], "aggfunc": {"销售额": np.sum, "库存量": np.mean} } pivot_result = dynamic_pivot(raw_data, **config) ``` #### 特点: 1. 通过字典参数动态控制行列布局[^2] 2. 支持多维度组合分析(最多支持3个层级) 3. 聚合函数可自定义扩展[^1] ### Excel交互式动态配置方案 ```python from openpyxl import load_workbook from openpyxl.pivot.table import Table, DataField def create_excel_pivot_template(output_path): wb = load_workbook() ws = wb.active # 创建数据透视框架 pivot = Table(displayName="DynamicPivot", ref="A1:D100", dataSheet=ws) # 添加可配置字段区域 pivot.cache = wb._pivot_caches.append(pivot.cache) wb.save(output_path) # 使用时在Excel界面手动拖拽字段配置[^3] ``` #### 优势: 1. 保持Excel的交互特性 2. 用户可自助调整字段布局 3. 支持实时刷新数据源 ### 、混合模式动态配置 ```python import yaml from pandas import ExcelWriter # 读取YAML配置文件 with open('pivot_config.yml') as f: config = yaml.safe_load(f) with ExcelWriter('report.xlsx', engine='openpyxl') as writer: # 生成多个透视 for table_cfg in config['pivot_tables']: pivot = pd.pivot_table(df, index=table_cfg['rows'], columns=table_cfg['columns'], values=table_cfg['values'], aggfunc=table_cfg.get('aggfunc', 'sum')) pivot.to_excel(writer, sheet_name=table_cfg['sheet_name']) # 添加数据透视对象 writer.book = load_workbook('report.xlsx') pivot_sheet = writer.book.create_sheet('PivotController') pivot_sheet.append(['字段类型', '可用字段列']) pivot_sheet.append(['行字段', ','.join(valid_columns)]) ``` #### 关键创新点: 1. 配置文件驱动(YAML/JSON) 2. 自动生成字段控制台 3. 支持批量生成多维度分析视图 ### 四、动态调整场景示例 假设需要根据用户输入实时生成不同维度的分析: ```python def realtime_pivot(df): while True: print("可用字段:", df.columns.tolist()) rows = input("输入行字段(逗号分隔):").split(',') cols = input("输入列字段(逗号分隔):").split(',') values = input("输入值字段:").split(',') print(pd.pivot_table(df, rows, cols, values)) if input('继续调整?(y/n)') != 'y': break ``` ### 五、性能优化建议 1. 使用分类数据类型优化内存 ```python for col in categorical_cols: df[col] = df[col].astype('category') ``` 2. 启用Dask处理超大规模数据 ```python import dask.dataframe as dd ddf = dd.from_pandas(df, npartitions=4) ``` 3. 缓存预处理结果 ```python from diskcache import Cache cache = Cache('./pivot_cache') @cache.memoize() def build_pivot(params): return dynamic_pivot(df, **params) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值