初学阶段,可以认为numpy的某些方法也可以运用到pandas模块中,例如np.where()三元运算、unique去重方法、shape方法
面板 数据 (三维数据)分析 计量经济学(数据分析80% 跑计量20%)
import numpy as np
import pandas as pd
# 创建一个符合正态分布的10个股票5天的涨跌幅数据
st_change = np.random.normal(0,1,(10,5))
st_change
这样的数据形式很难看到存储的是什么样的数据,并且也很难获取相应的数据,比如需要获取某个指定股票的数据,就很难去获取!!
# 使用Pandas中的数据结构
st_change = pd.DataFrame(st_change)
st_change
# 错误
# 构造行索引序列
st_code = ['股票'+str(i) for i in range(st_change.shape[0])]
print(st_code)
# 添加行索引
data = pd.DataFrame(st_change, index=st_code)
data
正确写法:
方法1:对dataframe结构的行索引index直接更改,有可能出问题,取决于赋什么值。以前这样做可以,现在不太推荐了
print(st_change.shape)
print(st_change.shape[0])
print(st_change.shape[1])
# 构造行索引序列
st_code = ['股票'+ str(i) for i in range(st_change.shape[0])]
print(st_code)
# 添加行索引
data = pd.DataFrame(st_change)
data.index = st_code
data
方法2:用rename方法改
df.rename(index={原行索引名:替换行索引名})
sort = huowu[huowu['优惠额度'] == '0'].groupby('货物名称').size()\
.sort_values(ascending=False)[:10].reset_index().set_index('货物名称')\
.rename(columns={0:'销量'})
date_range(start=None,end=None, periods=None, freq='B')
start:开始时间
end:结束时间
periods:时间天数
freq:递进单位,默认1天,'B'默认略过周末
# 生成一个时间的序列,略过周末非交易日
以下是错误代码,和上面可能出现错误的写法一样,全体nan值
# 生成一个时间的序列,略过周末非交易日
date = pd.date_range('2017-01-01', periods=stock_change.shape[1], freq='B')
# index代表行索引,columns代表列索引
data = pd.DataFrame(stock_change, index=stock_index, columns=date)
正确代码
# 增加列索引
# 股票的日期是一个时间的序列,我们要实现从前往后的时间还要考虑每月的总天数等,不方便。使用
# pd.date_range():用于生成一组连续的时间序列(暂时了解)
# 生成一个时间的序列,略过周末非交易日
date = pd.date_range('2017-01-01',periods=st_change.shape[1],freq='B')
# index代表行索引,columns代表列索引
data = pd.DataFrame(st_change)
data.columns = date
data
DataFrame对象既有行索引,又有列索引
常用属性:
huowu.head()
# 指标创建:不同优惠额度的订单数量
huowu.head()
huowu.index.name # None
huowu.columns.name # None
没有输出值,说明没有
data.shape
data.index
data.columns
data.values
data.T
col['color'] # 写法1
col.color # 写法2
原数据
X_new
X_new[:,0]
常用方法:
# 按列重新排序
data3 = data3.reindex(columns=['L','R','F','M','C'])
data3.head()
# 读取数据
# parse_dates参数作用:将csv中的时间字符串转换成日期格式
baidu = pd.read_csv(r'data2/baidu_index.csv',parse_dates=['Unnamed: 0']).set_index('Unnamed: 0')
baidu
# 将原有的索引名“Unnamed: 0”换值
baidu.index.name = 'date'
# 查看前5行和后5行数据
baidu.head().append(baidu.tail())
# 可以删掉订单数为0的用户,因为这部分客户暂时没有用处
guke3 = guke2
guke3.drop([0])
# 可以删掉订单数为0的用户,因为这部分客户暂时没有用处
guke3 = guke2
guke3
guke3.drop([0])
guke3
guke2.drop('客户类别',axis=1)
** 注意删除不改表原始数据**
删除后重新删除还是原来的数值,可以将删除行代码传给新的实参进行保留
st1.info()
但是要给原数据增加个新列,把修改后的列赋值过去,删除旧列,或者直接用新列覆盖旧列,然后才能用fillna方法进行替换,如以下代码
st1['close'] = st1['close'].astype(np.float)
st1['close'].fillna(st1['close'].mean(),inplace=True)
data.head(5)
data.tail(5)
baidu.describe()
# 其他指标改列索引
data3 = data2.rename(columns={
'FLIGHT_COUNT': 'F', 'avg_discount': 'C', 'SEG_KM_SUM': 'M', 'LAST_TO_END': 'R'}).drop(['FFP_DATE', 'LOAD_TIME'], axis=1)
data3
data5 = np.random.normal(0,1,(10,5))
data5 = pd.DataFrame(data5)
data5.rename(index={
0:1,2:22})
pc3.reset_index()
x.loc[0].tolist()
注意:以下修改方式是错误的
# 错误修改方式
data.index[3] = '股票_3'
#报错: TypeError: Index does not support mutable operations
# 错误
# 构造行索引序列
st_code = ['股票'+str(i) for i in range(st_change.shape[0])]
print(st_code)
# 添加行索引
data = pd.DataFrame(st_change, index=st_code)
data
正确的方式:
写法1:对dataframe结构的行索引index直接更改,有可能出问题,取决于赋什么值。以前这样做可以,现在不太推荐了
stock_code = ["股票_" + str(i) for i in range(stock_change.shape[0])]
# 必须整体全部修改
data.index = stock_code
写法2:用rename方法改
df.rename(index={原行索引名:替换行索引名})
data5 = np.random.normal(0,1,(10,5))
data5 = pd.DataFrame(data5)
data5.rename(index={0:1,2:22})
# 重置索引,drop=False
# 增加了列索引
data.reset_index()
# 重置索引,drop=True
# 删掉原来的行索引
data.reset_index(drop=True)
设置新索引案例
# 以某列值设置为新的索引
df = pd.DataFrame({'month': [1, 4, 7, 10],
'year': [2012, 2014, 2013, 2014],
'sale':[55, 40, 84, 31]})
print(df)
# 以月份设置新的索引
df.set_index('month')
# 设置多个索引,以年和月份
df.set_index(['year','month'])
注:通过刚才的设置,这样DataFrame就变成了一个具有MultiIndex的DataFrame。
# 读取数据
# parse_dates参数作用:将csv中的时间字符串转换成日期格式
baidu = pd.read_csv(r'data2/baidu_index.csv',parse_dates=['Unnamed: 0']).set_index('Unnamed: 0')
baidu
# 将原有的索引名“Unnamed: 0”换值
baidu.index.name = 'date'
# 查看前5行和后5行数据
baidu.head().append(baidu.tail())
data
# series
data['股票0']
type(data['股票0'])
# 这一步相当于是series去获取行索引的值
data
data['股票0']['2017-01-02']
通过已有数据创建
# 创建series
# 指定内容,默认索引
pd.Series(np.arange(10))
# 创建series
# 指定索引
pd.Series([6.7, 5.6, 3, 10, 2], index=[1, 2, 3, 4, 5])
# 创建series
# 通过字典数据创建
pd.Series({'red':100, 'blue':200, 'green': 500, 'yellow':1000})
data3 = pd.Series({'red':100, 'blue':200, 'green': 500, 'yellow':1000})
print(data3.index)
print(data3.values)
pandas库简介(1)–pandas的三种数据结构https://blog.csdn.net/zby1001/article/details/54234121
以下方法并非独一,可以有多种方式创建
baidu = [5408,10007,17817,39514,82117,140768,298637,406072,677541,858690,839792,744390,653541,496701,390412,322492,256334,212914,180933,157411,140104,120038,125914,105679,88426,75185,66567,61036,54812,49241,42768,35784,33774,33621,34388]
# len(baidu) # 35
date = pd.date_range('2018-1-15','2018-2-18')
date.shape # 35
baidu2 = pd.DataFrame(baidu,index=date,columns=['baidu_index'])
baidu2.head()
Numpy当中我们已经讲过使用索引选取序列和切片选择,pandas也支持类似的操作,也可以直接使用列名、行名称,甚至组合使用
# 2 基本数据操作
# 2.1 索引操作
# 2.1.2 结合loc或者iloc使用索引
# 使用loc:只能指定行列索引的名字
data5.loc[1:3,4]
data5.loc[1:3,2:4]
# 2 基本数据操作
# 2.1 索引操作
# 2.1.2 结合loc或者iloc使用索引
# 使用loc:只能指定行列索引的名字
data5.loc[1:3,4]
data5.loc[1:3,2:4]
data5.loc[[1,3],[2,4]]
# 2 基本数据操作
# 2.1 索引操作
# 2.1.2 结合loc或者iloc使用索引
# 使用iloc可以通过索引的下标去获取
data5.iloc[0:8,4:5] # 得到一列
data5.iloc[0:8,3:6]
data5.iloc[[1,3],[2,3]]
已经被弃用
# 2.2 赋值操作
# 直接修改原来的值
data5[1] = 4
data5
排序有两种形式,一种对内容进行排序,一种对索引进行排序
# 2.3 排序
# DataFrame排序
# 按照涨跌幅大小进行排序 , 使用ascending指定按照大小排序
data6 = data5.sort_values(by=3,ascending=False).head()
data6
# 2.3 排序
# DataFrame排序
# 按照多个键进行排序
data7 = data5.sort_values(by=[2,4])
data7
# 2.3 排序
# DataFrame排序
# 使用sort_index对索引进行排序
# 对索引进行排序
data7.sort_index()
# 显示默认显示行数
pd.set_option('display.max_rows', 80) # 设为None为显示所有行
# 设置默认显示列数
# pd.set_option('display.max_columns', None)
series排序时,只有一列,不需要参数
data5[4]
type(data5[4]) # pandas.core.series.Series
data5[4].sort_values(ascending=True).head()
data5[4].sort_index()
col['color'] # 写法1
col.color # 写法2
# 指定列检查
e1 = explore[['null','max','min']]
e1
col.color.value_counts()
# 3 DataFrame运算
# 3.1 算术运算
data5[1].add(1)
# 3 DataFrame运算
# 3.1 算术运算
data5
# 1、筛选两列数据
st = data5[0]
end = data5[1]
# 相减
data5[5] = end.sub(st)
data5
# 3 DataFrame运算
# 3.1 算术运算
# 乘
first = data5[1]
second = data5[2]
data5['乘'] = first.mul(second)
data5
# 3 DataFrame运算
# 3.1 算术运算
# 除 被除数.div(除数)
first = data5[1]
second = data5[2]
data5['除'] = second.div(first)
data5
# 3.2 逻辑运算
# 3.2.1 逻辑运算符号<、 >、|、 &
# 逻辑判断的结果可以作为筛选的依据
print(data5[2] > 0.5)
print(data5[data5[2]>0.5])
# 3.2 逻辑运算
# 3.2.1 逻辑运算符号<、 >、|、 &
data5[(data5[4]>0.1)&(data5[5]<4)]
# 3.2 逻辑运算
# 3.2.1 逻辑运算符号<、 >、|、 &
data5[(data5[4]>0.1)|(data5[5]<4)]
index1 = data.SUM_YR_1 != 0
在这里插入代码片
通过query使得刚才的过程更加方便简单
# 3.2 逻辑运算
# 3.2.2 逻辑运算函数
data5.query("乘>0 | 除>0")
# 3.2 逻辑运算
# 3.2.2 逻辑运算函数
data5[data5[1].isin([4])]
综合分析: 能够直接得出很多统计结果, count , mean , std , min , max 等
# 3.3 统计运算
# 3.3.1 describe()
# 计算平均值、标准差、最大值、最小值
data5.describe()
Numpy当中已经详细介绍,在这里我们演示min(最小值), max(最大值), mean(平均值), median(中位数), var(方差), std(标准差)结果
附上numpy的学习地址:
python使用numpy模块的介绍,基本操作,处理数据,包括生成数组,正态分布,均匀数组,数值改变,索引切片,形状修改,类型修改,数组去重,值运算,数组运算,合并分割,IO操作(读取)https://blog.csdn.net/weixin_55579895/article/details/120687601?spm=1001.2014.3001.5502
对于单个函数去进行统计的时候,坐标轴还是按照这些默认为“columns” (axis=0, default),如果要对行“index” 需要指定(axis=1)
# 3.3 统计运算
# 3.3.2 统计函数
# 使用统计函数:0 代表列求结果, 1 代表行求统计结果
data5.max()
# 3.3 统计运算
# 3.3.2 统计函数
# 方差
data5.var(1)
# 3.3 统计运算
# 3.3.2 统计函数
# 标准差
data5.std()
# 3.3 统计运算
# 3.3.2 统计函数
# 中位数
data5.median(0)
# 3.3 统计运算
# 3.3.2 统计函数
data5.idxmax(0)
data5.idxmax(axis=0)
# 3.3 统计运算
# 3.3.2 统计函数
data5.idxmin(0)
data5.idxmin(axis=0)
函数 | 作用 |
---|---|
cumsum | 计算前1/2/3/…/n个数的和(值一个个累计上去) |
cummax | 计算前1/2/3/…/n个数的最大值 |
cummin | 计算前1/2/3/…/n个数的最小值 |
cumprod | 计算前1/2/3/…/n个数的积 |
以上这些函数可以对series和dataframe操作
这里我们按照时间的从前往后来进行累计
# 3.4 累计统计函数
# 排序
data8 = data5.sort_index()
# 求和
st_0 = data8[0]
st_0.cumsum()
# data8
import matplotlib.pyplot as plt
# plot显示图形
st_0.cumsum().plot()
# 需要调用show,才能显示出结果
plt.show()
# 3.5 自定义运算
data5[[0,1]].apply(lambda x: x.max() - x.min(),axis=1)
更多参数细节:https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFram
e.plot.html?highlight=plot#pandas.DataFrame.plot
更多参数细节:https://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.plo
t.html?highlight=plot#pandas.Series.plot
我们的数据大部分存在于文件当中,所以pandas会支持复杂的IO操作,pandas的API支持众多的文件格式,如CSV、SQL、XLS、JSON、HDF5。
注:最常用的HDF5和CSV文件
### 5.1 CSV
### 5.1.1 读取csv文件-read_csv
# 读取文件,并且指定
data9 = pd.read_csv('stock_day.csv',usecols=['open','high','close'])
data9
# 读取数据
# parse_dates参数作用:将csv中的时间字符串转换成日期格式
baidu = pd.read_csv(r'data2/baidu_index.csv',parse_dates=['Unnamed: 0']).set_index('Unnamed: 0')
baidu
# 将原有的索引名“Unnamed: 0”换值
baidu.index.name = 'date'
# 查看前5行和后5行数据
baidu.head().append(baidu.tail())
to_csv的更多参数详解:pandas.read_csv参数详解
### 5.1 CSV
# 5.1.2 写入csv文件-to_csv
# 保存'open'列的数据
data9
# 选取10行数据保存,便于观察数据
data9[:10].to_csv('test1.csv',columns=['open'])
### 5.1 CSV
# 5.1.2 写入csv文件-to_csv
# 保存'open'列的数据
data9
# 选取10行数据保存,便于观察数据
data9[:10].to_csv('test1.csv',columns=['open'])
# 读取,查看结果
# 读取前先将打开检查的文件关闭否则报错 # [Errno 13] Permission denied: 'test1.csv'
pd.read_csv('test1.csv')
会发现将索引存入到文件当中,变成单独的一列数据。如果需要删除,可以指定index参数,删除原来的文件,重新保存一次。
# 会发现将索引存入到文件当中,变成单独的一列数据。如果需要删除,可以指定index参数,删除原来的文件,重新保存一次。
# index:存储不会将索引值变成一列数据
data9[:10].to_csv('test2.csv',columns=['open'],index=False)
# 指定追加方式
data9[:10].to_csv('test2.csv',columns=['open'],index=False,mode='a')
又存进了一个列名,所以当以追加方式添加数据的时候,一定要去掉列名columns,指定header=False
# 又存进了一个列名,所以当以追加方式添加数据的时候,一定要去掉列名columns,指定header=False
data9[:10].to_csv('test2.csv',columns=['open'],index=False,mode='a',header=False)
HDF5文件的读取和存储需要指定一个键,值为要存储的DataFrame
从h5文件当中读取数据
-path_or_buffer:文件路径
-key:读取的键
-mode:打开文件的模式
-return:Theselected object
# 5.2 HDF5
# 5.2.1 read_hdf与to_hdf
# 读取文件
day_high = pd.read_hdf('day_high.h5')
day_high
如果读取的时候出现以下错误
需要安装安装tables模块避免不能读取HDF5文件
pip install tables
# 5.2 HDF5
# 5.2.1 read_hdf与to_hdf
# 读取文件
day_high = pd.read_hdf('day_high.h5')
day_high
再次读取的时候, 需要指定键的名字
day_high.to_hdf('test.h5',key='day_high')
# 再次读取的时候, 需要指定键的名字
new_high = pd.read_hdf('test.h5',key='day_high')
new_high
Json是我们常用的一种数据交换格式,前面在前后端的交互经常用到,也会在存储的时候选择这种格式。所以我们需要知道Pandas如何进行读取和存储JSON格式。
Sarcasm_Headlines_Dataset.json
# 5.3.1 read_json
json_read = pd.read_json('Sarcasm_Headlines_Dataset.json',orient='records',lines=True)
json_read
# 5.3.2 to_json
json_read.to_json('test.json',orient='records')
# 修改lines参数为True
json_read.to_json('test.json',orient='records',lines=True)
- None 可以读取文件的所有表格
shop = pd.read_excel('2 电子商务平台数据分析实战1 - 数据规整和分析思路\data\shop.xlsx',None)
shop
优先选择使用HDF5文件存储
对于NaN的数据,在numpy中我们是如何处理的?在pandas中我们处理起来非常容易
电影数据文件获取
# 6 高级处理-缺失值处理
# 6.2 电影数据的缺失值处理
# 读取电影数据
st = pd.read_csv('pandas_day.csv')
st
# 6.2.1 判断缺失值是否存在
pd.notnull(st)
pandas删除缺失值,使用dropna的前提是,缺失值的类型必须是np.nan
# 6.2.2 存在缺失值nan,并且是np.nan
# 删除
# 不修改原数
st.dropna()
# 可以定义新的变量接受或者用原来的变量名
st1 = st.dropna()
st1
# 2、替换缺失值
# 替换存在缺失值的样本
# 替换填充平均值,中位数
st['high'].fillna(st['high'].mean(),inplace=True)
st
# 6.2.3 不是缺失值nan,有默认标记的
st = st.replace(to_replace='��',value=np.nan)
st
由于错误值的存在,已经将整列的数据类型变成了object字符串类型,不能使用fillna()方法来替换
方法1:直接删除
# 6.2.3 不是缺失值nan,有默认标记的
st1 = st.replace(to_replace='��',value=np.nan)
st1.mean()
st1
# 2、在进行缺失值的处理
# 删除
st2 = st1.dropna()
st2
先看前者,增加新的列
st1['colse1'] = st1['close'].astype(np.float)
st1.info()
# 6.2.3 不是缺失值nan,有默认标记的
st1 = st.replace(to_replace='��',value=np.nan)
# st1.mean()
st1.info()
# 2、在进行缺失值的处理
# 转整列格式
# 直接用新列覆盖旧列
st1['close'] = st1['close'].astype(np.float)
st1.info()
再使用fillna进行值的转换,修改成功
st1['close'].fillna(st1['close'].mean(),inplace=True)
st1
连续属性的离散化就是将连续属性的值域上,将值域划分为若干个离散的区间,最后用不同的符号或整数 值代表落在每个子区间中的属性值。
离散化有很多种方法,这使用一种最简单的方式去操作
这样我们将数据分到了三个区间段,我可以对应的标记为矮、中、高三个类别,最终要处理成一个“哑变量”矩阵。
连续属性离散化的目的是为了简化数据结构,数据离散化技术可以用来减少给定连续属性值的个数。离散化方法经常作为数据挖掘的工具。
案例:股票的涨跌幅离散化
我们对股票每日的"p_change"进行离散化
先读取股票的数据,筛选出p_change数据
# 7.3 如何实现数据的离散化
d1 = pd.read_csv('stock_day.csv')
d1
# 自行分组
qcut = pd.qcut(p_change,10)
# qcut
# 计算分到每个组数据个数
qcut.value_counts()
# 自行分组
qcut = pd.qcut(p_change,10)
qcut
# 自己指定分组区间
bins = [-100, -7, -5, -3, 0, 3, 5, 7, 100]
qcut1 = pd.cut(p_change,bins)
qcut1.value_counts()
du = pd.get_dummies(qcut,prefix='focus')
du
如果你的数据由多张表组成,那么有时候需要将不同的内容合并在一起分析
比如我们将刚才处理好的one-hot编码与原数据合并
# 8.1 pd.concat实现数据合并
pd.concat([d1,du],axis=1)
# 8.1 pd.concat实现数据合并
pd.concat([d1,du],axis=0)
如图中left的key1,key2和right的两行关联了两次,就将left的这一行复制一次变成两行
# 8.2.1 pd.merge合并
left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
'key2': ['K0', 'K1', 'K0', 'K1'],
'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3']})
right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
'key2': ['K0', 'K0', 'K0', 'K0'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})
# 默认内连接
result = pd.merge(left, right, on=['key1', 'key2'])
left
right
result
如图所示,第一行key值全部匹配直接合并,第二行key不匹配直接输出并补全nan值,第三行有两次相同的key值则复制一行填充
# 左连接
r2 = pd.merge(left,right,how='left',on=['key1','key2'])
r2
# 右连接
result = pd.merge(left, right, how='right', on=['key1', 'key2'])
result
# 外连接
result = pd.merge(left, right, how='outer', on=['key1', 'key2'])
result
直接相等,适用于索引项类型相同的情形
# 合并
# 方法1
guke2['客户类别'] = useful_cus['客户类别']
guke2
使用合并join函数
# 方法2 使用合并join函数
guke3 = guke.set_index('客户ID')
guke3.join(useful_cus['客户类别'])
探究股票的涨跌与星期几有关?
以下图当中表示,week代表星期几,1,0代表这一天股票的涨跌幅是好还是坏,里面的数据代表比例可以理解为所有时间为星期一等等的数据当中涨跌幅好坏的比例
交叉表(crosstab)和透视表(pivotTab)
透视表是将原有的DataFrame的列分别作为行索引和列索引,然后对指定的列应用聚集函数
交叉表用于统计分组频率的特殊透视表
df = pd.DataFrame({'类别':['水果','水果','水果','蔬菜','蔬菜','肉类','肉类'],
'产地':['美国','中国','中国','中国','新西兰','新西兰','美国'],
'水果':['苹果','梨','草莓','番茄','黄瓜','羊肉','牛肉'],
'数量':[5,5,9,3,2,10,8],
'价格':[5,5,10,3,3,13,20]})
df
# 透视表
df.pivot_table(index=['产地','类别'])
# 交叉表
pd.crosstab(df['类别'],df['产地'])
pd.crosstab(df['产地'],df['类别'])
透视表和交叉表的区别在代码上可能就是某个方法的转换,如mean()方法改成size()方法就是交叉表了
df.groupby(['类别','产地']).mean().unstack().fillna(0)
df.groupby(['类别','产地']).size().unstack().fillna(0)
# 9.2 使用crosstab(交叉表)
# 寻找星期几跟股票涨跌的关系
import numpy as np
# 1、先根据对应的日期找到星期几
date = pd.to_datetime(d1.index).weekday
# 创建新列加入周值
d1['week'] =date
# 2、把p_change按照大小分类,以0为界限
# 查看每一列的数据类型
type(d1['p_change']) # pandas.core.series.Series
# pandas的数据也可以使用numpy的三元运算
d1['p_judge'] = np.where(d1['p_change']>0,1,0)
# 通过交叉表找寻两列数据的关系
count = pd.crosstab(d1['week'],d1['p_judge'])
count
但是我们看到count只是每个星期日子的好坏天数,并没有得到比例,该怎么去做?
# 算数运算,先求和 axis=0按行统计,axis=1按列统计
sum = count.sum(axis=1).astype(np.float32)
print(sum)
# 进行相除操作,得出比例
per = count.div(sum,axis=0)
per
使用plot画出这个比例,使用stacked的柱状图
per.plot(kind='bar',stacked=True)
使用透视表,刚才的过程更加简单
它根据一个或多个键对数据进行聚合,并根据行和列上的分组键将数据分配到各个矩形区域中
# 9.3.3 使用pivot_table(透视表)实现
pivot = d1.pivot_table(['p_judge'],index=['week'])
print(pivot)
pivot.plot(kind='bar',stacked=True)
dingdan2.pivot_table('订单状态',index='客户ID',columns='优惠类型',fill_value=0,aggfunc=len)
dingdan2.pivot_table(index='客户ID',columns='优惠类型',fill_value=0,aggfunc=len)
dingdan2.pivot_table('订单状态',index='客户ID',columns='优惠类型',fill_value=0)
行数没有变化,但是只记录了是否有出现过0或者1的情况,并非计数
- 没有fill_value = 0
dingdan2.pivot_table('订单状态',index='客户ID',columns='优惠类型',aggfunc=len)
分组与聚合通常是分析数据的一种方式,通常与一些统计函数一起使用,查看数据的分组情况
想一想其实刚才的交叉表与透视表也有分组的功能,所以算是分组的一种形式,只不过他们主要是计算次数或者计算比例!!看其中的效果:
col.groupby('color').size() # size()显示每组的个数
stbuck.groupby(['Country','State/Province']).count()
stbuck.groupby(['Country','State/Province']).count().unstack()
# 10.2 分组API
col =pd.DataFrame({'color': ['white','red','green','red','green'], 'object':
['pen','pencil','pencil','ashtray','pen'],'price1':
[5.56,4.20,1.30,0.56,2.75],'price2':[4.75,4.12,1.60,0.75,3.15]})
col
# 分组,求平均值
col.groupby('color')['price1'].mean() # 写法1
col['price1'].groupby(col['color']).mean() # 写法2
col.groupby(['color'], as_index=False)['price1'].mean() # 写法3能变成dataframe结构
现在我们有一组关于全球星巴克店铺的统计数据,如果我想知道美国的星巴克数量和中国的哪个多,或者我想知道中国每个省份星巴克的数量的情况,那么应该怎么办?
数据来源:https://www.kaggle.com/starbucks/store-locations/data
# 10.3 星巴克零售店铺数据
# 导入星巴克店的数据
stbuck = pd.read_csv('directory.csv')
stbuck
# 按照国家分组,求出每个国家的星巴克零售店数量
country = stbuck.groupby(['Country']).count()
# country
# 画图显示结果
country['Brand'].plot(kind='bar',figsize=(20,8))
plt.show()
# 10.3 星巴克零售店铺数据
# 假设我们加入省市一起进行分组
# 设置多个索引
stbuck.groupby(['Country','State/Province']).count()
现在我们有一组从2006年到2016年1000部最流行的电影数据,数据来源(可能没用了):https://www.kaggle.com/d
amianpanek/sunday-eda/data
# 11 综合案例:电影数据
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 获取数据
df = pd.read_csv('Movie-Data.csv')
df
pandas模块和numpy模块可以综合使用解决问题,例如numpy的unique去重方法、shape方法
# 11 综合案例:电影数据
# 得到平均分
print('平均分:'+str(df['Rating'].mean()))
# 得出导演人数信息
# 求出唯一值,然后进行形状获取,使用numpy的去重方法unique
print('导演人数:'+str(np.unique(df['Director']).shape[0]))
选择分数列数据,进行plot
# 11 综合案例:电影数据
# 看Rating,Runtime (Minutes)的分布情况
df['Rating'].plot(kind='hist',figsize=(20,8))
# Rating进行分布展示
# 提取Rating列
# df['Rating']
# 提取rating列的所有数值
# df['Rating'].values
# 绘制直方图
plt.figure(figsize=(20,8),dpi=80)
plt.hist(df['Rating'].values,bins=20)
# 辅助显示
# 修改刻度的间隔
# 求出最大最小值
max_s = df['Rating'].max()
min_s = df['Rating'].min()
# 生成刻度列表
t1 = np.linspace(min_s,max_s,num=20)
print(len(t1))
# 修改刻度
plt.xticks(t1)
# 添加网格
plt.grid()
# Runtime (Minutes)进行分布展示
plt.figure(figsize=(20,8),dpi=80)
df['Runtime (Minutes)'].plot(kind='hist',figsize=(20,8))
# 辅助显示
# 修改刻度的间隔
# 求出最大最小值
max_s = df['Runtime (Minutes)'].max()
min_s = df['Runtime (Minutes)'].min()
# 生成刻度列表
t1 = np.linspace(min_s,max_s,num=20)
print(len(t1))
# 修改刻度
plt.xticks(t1)
# 添加网格
plt.grid()
# 11.2.3 统计电影分类(genre)的情况
# 每一部电影的分类可能并非单一
# for i in df['Genre']:
# print(i)
# 进行字符串分割
temp_list = [i.split(',') for i in df['Genre']]
# for i in temp_list:
# print(i)
# 获取电影的分类,遍历种类中的每一个值,
# 放进一个新列表里面,并进行np.unique区中,得到了所有的种类
# for i in temp_list:
# for j in i:
# print(j)
gen_list = np.unique([j for i in temp_list for j in i])
gen_list
# 在原来的dataframe数据df中增加新的列,使用np.zeros方法生成0和1的数组
print(gen_list.shape[0]) # 增加各种种类的列(20个)
print(df.shape[0]) # 增加行数(1000行)
gen_np = np.zeros([df.shape[0],gen_list.shape[0]])
# gen_df.shape # (1000, 20)
# 变成dataframe数据结构
# 指定新增各列的名称,正好是电影种类列的数值
gen_df = pd.DataFrame(gen_np,columns=gen_list)
gen_df
分析匹配的方法
# 2、遍历每一部电影,temp_df中把分类出现的列的值置为1
# 2.1 temp_list中有电影的种类标签,和gen_df的长度是对应的
# temp_list
# 2.2 使用temp_list的行标签,gen_df的列标签来匹配到对应的种类
# 使用pd.loc方法匹配行数和列的名称,注意不要使用iloc方法,iloc方法是用来匹配列的位置下标
temp_list[0] # ['Action', 'Adventure', 'Sci-Fi']
gen_df.loc[[0],temp_list[0]]
# 遍历赋值
for i in range(df.shape[0]):
gen_df.loc[[i],temp_list[i]] = 1
# gen_df
# gen_df
# 求和并排序
gen_result = gen_df.sum().sort_values(ascending=False)
# 画图显示
gen_result.plot(kind='bar',figsize=(20,8),fontsize=20,colormap='cool')