python/pandas数据挖掘 groupby,聚合

本文介绍Pandas库中groupby方法的使用技巧,包括基于不同类型的键进行分组、迭代分组结果、转换分组内容及应用自定义函数进行数据聚合等高级用法。

python/pandas数据挖掘(十四)-groupby,聚合,分组级运算

groupby

import pandas as pd
df = pd.DataFrame({'key1':list('aabba'),
                  'key2': ['one','two','one','two','one'],
                  'data1': np.random.randn(5),
                  'data2': np.random.randn(5)})
df
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这里写图片描述

grouped=df['data1'].groupby(df['key1'])
grouped.mean()
  • 1
  • 2

以上的分组键均为Series,实际上分组键可以是任何长度适当的数组

states=np.array(['Ohio','California','California','Ohio','Ohio'])
years=np.array([2005,2005,2006,2005,2006])
df['data1'].groupby([states,years]).mean()
  • 1
  • 2
  • 3

这里写图片描述

df.groupby('key1').mean()
  • 1

这里写图片描述

可以看出没有key2列,因为df[‘key2’]不是数值数据,所以被从结果中移除。默认情况下,所有数值列都会被聚合,虽然有时可能被过滤为一个子集。

对分组进行迭代

for name, group in df.groupby('key1'):
        print (name)
        print (group)
  • 1
  • 2
  • 3

这里写图片描述

可以看出name就是groupby中的key1的值,group就是要输出的内容。 
同理:

for (k1,k2),group in df.groupby(['key1','key2']):
    print ('===k1,k2:')
    print (k1,k2)
    print ('===k3:')
    print (group)
  • 1
  • 2
  • 3
  • 4
  • 5

这里写图片描述

对group by后的内容进行操作,如转换成字典

piece=dict(list(df.groupby('key1')))
piece

{'a':       data1     data2 key1 key2
 0 -0.233405 -0.756316    a  one
 1 -0.232103 -0.095894    a  two
 4  1.056224  0.736629    a  one, 'b':       data1     data2 key1 key2
 2  0.200875  0.598282    b  one
 3 -1.437782  0.107547    b  two}


piece['a']
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

这里写图片描述

groupby默认是在axis=0上进行分组的,通过设置也可以在其他任何轴上进行分组.

grouped=df.groupby(df.dtypes, axis=1)
dict(list(grouped))

{dtype('float64'):       data1     data2
 0 -0.233405 -0.756316
 1 -0.232103 -0.095894
 2  0.200875  0.598282
 3 -1.437782  0.107547
 4  1.056224  0.736629, dtype('O'):   key1 key2
 0    a  one
 1    a  two
 2    b  one
 3    b  two
 4    a  one
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

选取一个或者一组列

这里写图片描述 
对于大数据,很多情况是只需要对部分列进行聚合

df.groupby(['key1','key2'])[['data2']].mean()
  • 1
  • 2

这里写图片描述

通过字典或者series进行分组

people=pd.DataFrame(np.random.randn(5,5),
                   columns=list('abcde'),
                   index=['Joe','Steve','Wes','Jim','Travis'])

people.ix[2:3,['b','c']]=np.nan #设置几个nan
people
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这里写图片描述

已知列的分组关系

mapping={'a':'red','b':'red','c':'blue','d':'blue','e':'red','f':'orange'}

by_column=people.groupby(mapping,axis=1)

by_column.sum()
  • 1
  • 2
  • 3
  • 4
  • 5

这里写图片描述

如果不加axis=1, 则只会出现 a b c d e

Series 也一样

map_series=pd.Series(mapping)
map_series

a       red
b       red
c      blue
d      blue
e       red
f    orange
dtype: object

people.groupby(map_series,axis=1).count()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

这里写图片描述

通过函数进行分组

相较于dic或者Series,python函数在定义分组关系映射时更有创意。任何被当做分组键的函数都会在各个索引上被调用一次,其返回值就会被用作分组名称。假设你按人名的长度进行分组,仅仅传入len即可


people.groupby(len).sum() a b c d e 3 -1.308709 -2.353354 1.585584 2.908360 -1.267162 5 -0.688506 -0.187575 -0.048742 1.491272 -0.636704 6 0.110028 -0.932493 1.343791 -1.928363 -0.364745
  • 1
  • 2

将函数和数组、列表、字典、Series混合使用也不是问题,因为任何东西都会最终转换为数组

 key_list=['one','one','one','two','two'] people.groupby([len,key_list]).sum()
  • 1

根据索引级别进行分组

层次化索引最方便的地方就在于他能够根据索引级别进行聚合。要实现该目的,通过level关键字出入级别编号或者名称即可:

columns=pd.MultiIndex.from_arrays([['US','US','US','JP','JP'],[1,3,5,1,3]],names=['cty','tenor'])
hier_df=pd.DataFrame(np.random.randn(4,5),columns=columns)
hier_df
  • 1
  • 2
  • 3

这里写图片描述

hier_df.groupby(level='cty',axis=1).count()
  • 1

这里写图片描述

数据聚合

调用自定义的聚合函数

这里写图片描述

这里写图片描述

面向列的多函数应用

对Series或者DataFrame列的聚合运算实际是使用aggregate或者调用mean,std等方法。下面我们想对不同的列使用不同的聚合函数,或者一次应用多个函数

grouped=tips.groupby(['sex','smoker'])
grouped_pct=grouped['tip_pct'] #tip_pct列
grouped_pct.agg('mean')#对与9-1图标中描述的统计,可以将函数名直接以字符串传入

#如果传入一组函数,得到的df的列名就会以相应的函数命名
  • 1
  • 2
  • 3
  • 4
  • 5

这里写图片描述

自动给出的列名辨识度低,如果传入的是(name, function)元组组成的列表,则各个元组的第一个元素将被用作df的列名

这里写图片描述

对于df,可以定义一组用于全部列的函数,或在不同的列应用不同的函数 
这里写图片描述

如果想对不同的列应用不同的函数, 具体的办法是想agg传入一个从列名映射到函数的字典 
这里写图片描述 
只有将多个函数应用到至少一列时,df才能拥有层次化的列

分组级运算和转换

聚合只是分组运算的一种,它是数据转换的特列。transform 和apply更牛叉.

transform会将一个函数应用到各个分组,然后将结果放在适当的位置. 如果各分组产生的标量值,则该标量值会被广播出去。

transform也是有严格条件的特殊函数:传入的函数只能产生两种结果,要么产生一个可以广播的标量值(如:np.mean), 要么产生一个相同大小的结果数组。

people=pd.DataFrame(np.random.randn(5,5),
                   columns=list('abcde'),
                   index=['Joe','Steve','Wes','Jim','Travis'])
people
  • 1
  • 2
  • 3
  • 4
  • 5

这里写图片描述

key=['one','two','one','two','one']
people.groupby(key).mean()
  • 1
  • 2

这里写图片描述

people.groupby(key).transform(np.mean)
  • 1

这里写图片描述

可以看到有很多与表2一样的值。

def demean(arr):
    return arr-arr.mean()

demeaned=people.groupby(key).transform(demean)
demeaned
  • 1
  • 2
  • 3
  • 4
  • 5
demeaned.groupby(key).mean()
  • 1

最一般化的groupby 方法是apply.

tips=pd.read_csv('C:\\Users\\ecaoyng\\Desktop\\work space\\Python\\py_for_analysis_code\\pydata-book-master\\ch08\\tips.csv')
tips[:5]
  • 1
  • 2

这里写图片描述

新生成一列

tips['tip_pct']=tips['tip']/tips['total_bill']
tips[:6]
  • 1
  • 2

这里写图片描述

根据分组选出最高的5个tip_pct值

def top(df,n=5,column='tip_pct'):
    return df.sort_index(by=column)[-n:]
top(tips,n=6)
  • 1
  • 2
  • 3

这里写图片描述

对smoker分组并应用该函数

tips.groupby('smoker').apply(top)
  • 1

这里写图片描述

多参数版本

tips.groupby(['smoker','day']).apply(top,n=1,column='total_bill')
  • 1

这里写图片描述

分位数和桶分析

cut and qcut与groupby结合起来,能轻松的对数据集的桶(bucket)或者分位数(quantile)分析。

frame=pd.DataFrame({'data1':np.random.randn(1000),
                   'data2': np.random.randn(1000)})
frame[:5]
  • 1
  • 2
  • 3

这里写图片描述

factor=pd.cut(frame.data1,4)
factor[:10]

0    (0.281, 2.00374]
1    (0.281, 2.00374]
2    (-3.172, -1.442]
3     (-1.442, 0.281]
4    (0.281, 2.00374]
5    (0.281, 2.00374]
6     (-1.442, 0.281]
7     (-1.442, 0.281]
8     (-1.442, 0.281]
9     (-1.442, 0.281]
Name: data1, dtype: category
Categories (4, object): [(-3.172, -1.442] < (-1.442, 0.281] < (0.281, 2.00374] < (2.00374, 3.727]]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
def get_stats(group):
    return {'min':group.min(),'max':group.max(),'count':group.count(),'mean':group.mean()}
grouped=frame.data2.groupby(factor)
grouped.apply(get_stats).unstack()
  • 1
  • 2
  • 3
  • 4

这里写图片描述

这些都是长度相等的桶,要根据样本分为数得到大小相等的桶,使用qcut即可.

长度相等的桶:区间大小相等 
大小相等的桶:数据点数量相等

grouping=pd.qcut(frame.data1,10,labels=False)#label=false即可值获取分位数的编号
grouped=frame.data2.groupby(grouping)
grouped.apply(get_stats).unstack()
  • 1
  • 2
  • 3

这里写图片描述

<think>好的,用户现在想了解如何使用PythonPandas进行基础数据分析的方法和技巧。首先,我需要回顾一下之前的对话历史,看看用户之前问过什么,以及我之前给出的回答。之前用户询问了工业物联网的技术排序,而我在回答中提到了Pandas在数据分析中的应用,引用了多个相关的资料。现在用户明确转向了基础数据分析,特别是使用PythonPandas的操作方法和技巧。 用户提供的引用内容主要集中在Pandas的数据结构、数据读取、清洗、分析以及可视化等方面。例如,引用[1]提到如何用Pandas读取和写入MySQL数据,引用[2]和[4]讨论了Pandas的核心数据结构和实战分析,引用[3]和[5]则涉及数据预处理和可视化工具。这些内容都是基础数据分析的关键部分,因此需要整合这些信息来构建回答。 接下来,我需要确定用户的需求层次。用户可能是一个刚开始学习数据分析的新手,想要了解从数据加载到分析的基本流程。他们可能需要具体的代码示例和步骤说明,而不仅仅是理论解释。因此,回答需要结构清晰,分步骤讲解,每个步骤提供实际的代码示例,并解释每个操作的目的和效果。 同时,用户提到“方法和技巧”,这意味着除了基础操作外,还需要包含一些提升效率的技巧或最佳实践。比如,使用向量化操作代替循环,合理设置数据类型节省内存,或者如何利用Pandas的内置函数进行高效分析。这些内容可以增强回答的实用性。 另外,需要参考之前提供的引用内容。例如,引用[3]中提到了数据处理的标准化流程,如处理缺失值、变量筛选等,这应该在数据清洗部分详细说明。引用[4]提到的数据透视表也是一个重要技巧,应该包含在数据分析的方法中。引用[5]中的可视化部分可以使用pyecharts或matplotlib来展示结果,但考虑到用户是新手,可能更倾向于使用Pandas内置的绘图功能,或者结合简单的可视化库如Seaborn。 在组织内容时,应该按照数据分析的典型流程:数据加载、数据观察、数据清洗、数据分析、数据可视化,最后是一些实用技巧。每个部分都需要结合代码示例,并引用相关的资料来支持说明。例如,在数据加载部分,可以引用[1]中的方法从MySQL读取数据,同时提到其他格式如CSV的读取方式。在数据清洗时,引用[3]提到的缺失值处理和变量筛选方法。 还需要注意用户可能的痛点,比如如何处理大型数据集,避免内存不足,或者如何提升处理速度。这时候可以提到使用适当的数据类型,分块读取数据,或者使用Dask库进行并行处理。这些技巧虽然稍微进阶,但对新手来说是有用的信息。 最后,要确保回答的语言简洁明了,避免使用过于专业的术语,或者在必要时进行解释。例如,解释什么是DataFrame,或者什么是向量化操作,以便用户能够更好地理解。此外,提供相关的参考资料链接或引用标识,如[^1]、[^2]等,增强回答的可信度。 总结来说,回答的结构应包括以下几个部分: 1. 环境准备与数据加载 2. 数据观察与统计 3. 数据清洗(处理缺失值、重复值、异常值) 4. 数据分析(聚合、分组、透视表) 5. 数据可视化 6. 实用技巧与优化建议 每个部分都需要具体的代码示例,并结合引用内容中的知识点进行说明。同时,在最后提出相关问题,引导用户深入学习和探索更高级的主题,如处理大数据集或时间序列分析,这样可以扩展他们的学习路径。</think>### 如何使用 PythonPandas 进行基础数据分析 #### 一、环境准备与数据加载 1. **安装与导入库** ```python import pandas as pd import numpy as np ``` 2. **数据加载** - **从 CSV 文件读取**: ```python df = pd.read_csv('data.csv') ``` - **从 MySQL 数据库读取**(引用[1]): ```python import pymysql conn = pymysql.connect(host='localhost', user='root', password='123456', database='test') df = pd.read_sql('SELECT * FROM sales', conn) ``` - **从 Excel 读取**: ```python df = pd.read_excel('data.xlsx', sheet_name='Sheet1') ``` --- #### 二、数据观察与统计 1. **初步查看数据** ```python df.head() # 查看前5行 df.info() # 数据类型与非空值统计 df.describe() # 数值型字段统计(均值、标准差、分位数等) ``` 2. **筛选与排序** ```python df[['列A', '列B']] # 选择特定列 df[df['销售额'] > 1000] # 条件筛选 df.sort_values('日期') # 按日期排序 ``` --- #### 三、数据清洗(关键步骤) 1. **处理缺失值**(引用[3]) ```python df.dropna() # 删除含缺失值的行 df.fillna(0) # 用0填充缺失值 df['列C'].fillna(df['列C'].mean(), inplace=True) # 用均值填充 ``` 2. **处理重复值** ```python df.drop_duplicates() # 删除完全重复的行 ``` 3. **处理异常值** ```python df = df[(df['年龄'] > 0) & (df['年龄'] < 100)] # 过滤年龄异常值 ``` --- #### 四、数据分析 1. **聚合计算** ```python df.groupby('地区')['销售额'].sum() # 按地区统计销售额总和 ``` 2. **数据透视表**(引用[4]) ```python pivot_table = df.pivot_table( values='销量', index='地区', columns='季度', aggfunc='mean' ) ``` 3. **时间序列分析** ```python df['日期'] = pd.to_datetime(df['日期']) # 转换为时间格式 df.set_index('日期', inplace=True) # 设为索引 df.resample('M')['销售额'].sum() # 按月汇总销售额 ``` --- #### 五、数据可视化 1. **内置绘图** ```python df['销售额'].plot(kind='line') # 折线图 df['地区'].value_counts().plot(kind='bar') # 柱状图 ``` 2. **使用 pyecharts**(引用[5]) ```python from pyecharts.charts import Line line = Line().add_xaxis(df['日期'].tolist()).add_yaxis("销售额", df['销售额'].tolist()) line.render("sales_trend.html") # 生成交互式图表 ``` --- #### 六、实用技巧 1. **向量化操作替代循环** ```python # 错误方式(逐行循环) for index, row in df.iterrows(): df.loc[index, '利润'] = row['销售额'] - row['成本'] # 正确方式(向量化计算) df['利润'] = df['销售额'] - df['成本'] ``` 2. **优化内存占用** ```python df['类别'] = df['类别'].astype('category') # 将文本列转换为分类类型 ``` 3. **高效筛选** ```python df.query('销售额 > 1000 & 地区 == "华东"') # 使用query方法简化条件 ``` --- ### 示例代码:完整分析流程 ```python # 数据加载与清洗 df = pd.read_csv('sales.csv') df.dropna(subset=['销售额'], inplace=True) df['日期'] = pd.to_datetime(df['日期']) # 数据分析 monthly_sales = df.resample('M', on='日期')['销售额'].sum() top_products = df.groupby('产品')['销量'].sum().nlargest(5) # 可视化 monthly_sales.plot(title='月度销售额趋势', figsize=(10,6)) ``` --- ### 相关问题 1. 如何处理 Pandas 中的大型数据集内存不足问题? 2. 如何用 Pandas 实现时间序列预测分析? 3. Pandas 与 SQL 在数据处理上的效率对比? 以上方法覆盖了数据加载、清洗、分析和可视化的核心操作,结合引用[1]-[5]的实践技巧,可快速掌握基础数据分析能力[^1][^2][^3][^4][^5]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值