day01:pandas数据分析

 

山顶会课程概述¶

  • 【数分+开发为主题】,迎合多维度接单
  • 课程排期问题
  • 课程大致内容

   

数据分析基本概述¶

   

什么是数据分析?¶

   

所谓的数据分析就是使用一些有效的方法和工具对收集到的数据进行处理,从中发现数据的关键趋势或者规律,以便做出合理的决策和提出有针对性的建议。通俗来说,数据分析就是从数据中找到有用的信息来帮助我们做出更明智、更准确的决策。

   

总之,数据分析是将数据转化为可理解的信息和见解,可为业务提供决策信息、帮助解决问题和提高效率的过程。本质上,所有的决策、战略和规划都需要数据驱动,数据分析在这个过程中起到了突出的作用。

   

简单一句话描述数据分析:数据分析可以实现数据价值的最大化!

   

数据分析的技术实现¶

   

不写代码的实现¶

处理简单或者普通难度的业务逻辑的分析处理

   

  • Excel
  • Mysql
  • BI工具(PowerBI或者Tableau)

   

写代码的实现¶

处理普通难度的业务逻辑的分析处理+复杂的业务逻辑处理

  • Python
    • 数据分析三剑客:Numpy、Pandas和Matplotlib

   

  • 开发环境安装:
    • 链接: https://pan.baidu.com/s/1xI-RafNRZKDQPI7WMSmd2A?pwd=6x2v 提取码: 6x2v
    • anaconda:数据分析的集成环境(包含了各种数据分析的模块)

   

Numpy¶

   

NumPy(Numerical Python)是Python中用于数据分析、机器学习、科学计算的重要工具包,也是python进行科学计算重要基础库之一,多数值运算。

   

Pandas(重点)¶

   

Pandas 库是一个免费、开源的第三方 Python 库,是 Python 数据分析和机器学习必不可少的工具之一,它为 Python 数据分析提供了高性能,且易于使用的数据结构,即 Series 和 DataFrame。Pandas 自诞生后被应用于众多的领域,比如金融、统计学、社会科学、建筑工程等。

Pandas 库基于 Python NumPy 库开发而来,因此,它可以与 Python 的科学计算库配合使用。Pandas 提供了两种数据结构,分别是 Series(一维数组结构)与 DataFrame(二维表格结构),这两种数据结构极大地增强的了 Pandas 的数据分析能力。

   

数据结构介绍:数据存储在不同的数据结构表示的容器中,则可以基于容器的特性对数据进行不同维度的运算处理操作。

   

   

Matplotlib¶

   

matplotlib是一个用于创建可视化图表的Python库。它提供了一组广泛的功能,用于绘制线图、散点图、柱状图、饼图、等高线图、热图等各种类型的图表。

matplotlib是一个功能强大且灵活的库,被广泛应用于数据可视化、科学计算、工程绘图等领域。

图表绘制在数据分析中主要用户进行数据探索和分析结果的展示。

   

 

   

pandas数据分析库¶

Pandas 提供了两种数据结构,分别是 Series(一维数组结构)与 DataFrame(二维数组结构),这两种数据结构极大地增强的了 Pandas 的数据分析能力。

Series¶

概述¶

Series是一种类似与一维数组的对象,由下面两个部分组成:

  • values:一组数据
  • index:相关的数据索引标签

常见操作¶

  • 创建方式
    • 由列表创建
    • 由字典创建

  In [60]:

import pandas as pd
from pandas import Series,DataFrame

  In [64]:

s1 = Series(data=[3,3,6,6,8,8,9,9])
s1

  Out[64]:

0    3
1    3
2    6
3    6
4    8
5    8
6    9
7    9
dtype: int64

  In [62]:

s2 = Series(data={'name':'bobo','salary':10000,'age':30})
s2

  Out[62]:

name       bobo
salary    10000
age          30
dtype: object

   

  • Series的索引

    • 隐式索引:默认形式的索引(0,1,2….)
    • 显示索引:自定义的索引,可以通过index参数设置显示索引
      • 显示索引的作用:增加了数据的可读性

  In [66]:

s1[[0,2,4]] #通过隐式索引访问元素

  Out[66]:

0    3
2    6
4    8
dtype: int64

  In [69]:

s2['name']

  Out[69]:

'bobo'

   

  • Series的索引和切片

  In [73]:

s1[0:3]

  Out[73]:

0    3
1    3
2    6
dtype: int64

  In [74]:

s2['name':'age']

  Out[74]:

name       bobo
salary    10000
age          30
dtype: object

   

  • Series的常用方法

    • head(),tail()
    • unique(),nunique()
    • value_counts()
    • isnull(),notnull()

  In [76]:

s1.head(3),s1.tail(2) #用来显示前几个或者后几个元素

  Out[76]:

(0    3
 1    3
 2    6
 dtype: int64,
 6    9
 7    9
 dtype: int64)

  In [78]:

s1.unique() #元素去重

  Out[78]:

array([3, 6, 8, 9])

  In [79]:

s1.nunique() #统计去重后元素的个数

  Out[79]:

4

  In [80]:

s1.value_counts() #统计元素出现的次数

  Out[80]:

3    2
6    2
8    2
9    2
dtype: int64

  In [82]:

#series的运算
s1 + 100 #让s1的每一个元素都加上100

  Out[82]:

0    103
1    103
2    106
3    106
4    108
5    108
6    109
7    109
dtype: int64

  In [83]:

s3 = Series(data=[1,2,3],index=['a','b','c'])
s3

  Out[83]:

a    1
b    2
c    3
dtype: int64

  In [84]:

s4 = Series(data=[1,2,3],index=['a','b','d'])
s4

  Out[84]:

a    1
b    2
d    3
dtype: int64

  In [85]:

s3 + s4 #NAN就是None
#在Series的运算中,只有索引一致的元素可以进行算数运算,否则补空

  Out[85]:

a    2.0
b    4.0
c    NaN
d    NaN
dtype: float64

   

DataFrame(重要)¶

概述¶

  • DataFrame是一个【表格型】的数据结构。DataFrame由按一定顺序排列的多列数据组成。设计初衷是将Series的使用场景从一维拓展到多维。DataFrame既有行索引,也有列索引。
    • 行索引:index
    • 列索引:columns
    • 值:values

DataFrame的创建¶

  • 字典创建

  In [87]:

dic = {
    'name':['Tom','Jerry','Jay'],
    'age':[10,20,30],
    'salary':[2000,3000,4000]
}
table = DataFrame(data=dic)
table

  Out[87]:  

  name age salary
0 Tom 10 2000
1 Jerry 20 3000
2 Jay 30 4000

   

DataFrame的常用属性¶

  • values,columns,index,shape

  In [88]:

table.shape #表格的形状

  Out[88]:

(3, 3)

  In [89]:

table.values #返回表格所有的值

  Out[89]:

array([['Tom', 10, 2000],
       ['Jerry', 20, 3000],
       ['Jay', 30, 4000]], dtype=object)

  In [90]:

table.index #行索引

  Out[90]:

RangeIndex(start=0, stop=3, step=1)

  In [91]:

table.columns #列索引

  Out[91]:

Index(['name', 'age', 'salary'], dtype='object')

   

索引操作(重点)¶

  • 对行进行索引
  • 队列进行索引
  • 对元素进行索引

  In [93]:

dic = {'names':['jay','tom','jerry'],
       'salary':[1000,2000,3000],
      'age':[30,40,50]}
df = DataFrame(data=dic,index=['a','b','c'])
df

  Out[93]:  

  names salary age
a jay 1000 30
b tom 2000 40
c jerry 3000 50

  In [94]:

#索引取单列:df[col]
df['age']

  Out[94]:

a    30
b    40
c    50
Name: age, dtype: int64

  In [95]:

#索引取多列:df[[col1,coln]]
df[['age','names']]

  Out[95]:  

  age names
a 30 jay
b 40 tom
c 50 jerry

  In [96]:

#索引取单行:df.loc/iloc[index]
df.loc['a']

  Out[96]:

names      jay
salary    1000
age         30
Name: a, dtype: object

  In [99]:

df.iloc[0] #iloc后面跟的是隐式索引,loc后面跟显示索引

  Out[99]:

names      jay
salary    1000
age         30
Name: a, dtype: object

  In [100]:

#索引取多行:df.loc/iloc[[index1,indexn]]
df.loc[['b','a']]

  Out[100]:  

  names salary age
b tom 2000 40
a jay 1000 30

  In [102]:

df

  Out[102]:  

  names salary age
a jay 1000 30
b tom 2000 40
c jerry 3000 50

  In [104]:

#索引取元素
df.loc['b','names'] #逗号左边是行,右边是列

  Out[104]:

'tom'

   

切片操作¶

  • 批量切行
  • 批量切列

  In [105]:

#切行
df['a':'c']

  Out[105]:  

  names salary age
a jay 1000 30
b tom 2000 40
c jerry 3000 50

  In [106]:

#切列
df.loc[:,'names':'salary']

  Out[106]:  

  names salary
a jay 1000
b tom 2000
c jerry 3000

   

数据查看¶

  • 查看DataFrame的概览和统计信息
    • head()
    • tail()
    • info()
    • describe()

  In [109]:

df.info() #查看表格的基本信息

   

<class 'pandas.core.frame.DataFrame'>
Index: 3 entries, a to c
Data columns (total 3 columns):
 #   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 
 0   names   3 non-null      object
 1   salary  3 non-null      int64 
 2   age     3 non-null      int64 
dtypes: int64(2), object(1)
memory usage: 204.0+ bytes

  In [110]:

df.describe() #对数据表格进行统计描述

  Out[110]:  

  salary age
count 3.0 3.0
mean 2000.0 40.0
std 1000.0 10.0
min 1000.0 30.0
25% 1500.0 35.0
50% 2000.0 40.0
75% 2500.0 45.0
max 3000.0 50.0

   

数据保存与加载¶

csv¶
  • to_csv() & read_csv()

  In [112]:

#将df数据写入到文件中存储
dic = {'names':['jay','tom','jerry'],
       'salary':[1000,2000,3000],
      'age':[30,40,50]}
df = pd.DataFrame(data=dic,index=['a','b','c'])
df

  Out[112]:  

  names salary age
a jay 1000 30
b tom 2000 40
c jerry 3000 50

  In [113]:

df.to_csv('./df.csv')

  In [114]:

#读取外部文件 ./data/透视表-篮球赛.csv的数据到df表格中
ball = pd.read_csv('data/透视表-篮球赛.csv')
ball

  Out[114]:  

  对手 胜负 主客场 命中 投篮数 投篮命中率 3分命中率 篮板 助攻 得分
0 勇士 10 23 0.435 0.444 6 11 27
1 国王 8 21 0.381 0.286 3 9 27
2 小牛 10 19 0.526 0.462 3 7 29
3 灰熊 8 20 0.400 0.250 5 8 22
4 76人 10 20 0.500 0.250 3 13 27
5 黄蜂 8 18 0.444 0.400 10 11 27
6 灰熊 6 19 0.316 0.222 4 8 20
7 76人 8 21 0.381 0.429 4 7 29
8 尼克斯 9 23 0.391 0.353 5 9 31
9 老鹰 8 15 0.533 0.545 3 11 29
10 爵士 19 25 0.760 0.875 2 13 56
11 骑士 8 21 0.381 0.429 11 13 35
12 灰熊 11 25 0.440 0.429 4 8 38
13 步行者 9 21 0.429 0.250 5 15 26
14 猛龙 8 25 0.320 0.273 6 11 38
15 太阳 12 22 0.545 0.545 2 7 48
16 灰熊 9 20 0.450 0.500 5 7 29
17 掘金 6 16 0.375 0.143 8 9 21
18 尼克斯 12 27 0.444 0.385 2 10 37
19 篮网 13 20 0.650 0.615 10 8 37
20 步行者 8 22 0.364 0.333 8 10 29
21 湖人 13 22 0.591 0.444 4 9 36
22 爵士 8 19 0.421 0.333 5 3 29
23 开拓者 16 29 0.552 0.571 8 3 48
24 鹈鹕 8 16 0.500 0.400 1 17 26

   

Excel¶

环境安装:

pip install xlrd -i https://pypi.tuna.tsinghua.edu.cn/simple

pip install xlwt -i https://pypi.tuna.tsinghua.edu.cn/simple

pip install openpyxl -i https://pypi.tuna.tsinghua.edu.cn/simple

  • to_excel(filaPath,sheet_name) & read_excel(filaPath,sheet_name)
    • sheet_name工作表名称

  In [116]:

#读取excel数据:data/运营商数据.xlsx
opt = pd.read_excel('data/运营商数据.xlsx')
opt

  Out[116]:  

  用户号码 用户套餐月租 入网时间 近6个月平均话费 近6个月平均使用流量 近6个月平均使用语音 优惠名称 号码品牌 用户年龄 用户性别 是否订购 是否参与活动 活动开始时间 活动结束时间 外呼团队 外呼时间 外呼分钟数
0 1 56 20020209 146.2050 9090.910500 398.3167 送3个月会员 4G 55 NaN NaN NaN NaN 201911 91
1 2 50 20060424 50.0000 3980.592767 86.9000 送3个月会员 4G 51 NaN NaN NaN NaN 201909 28
2 3 50 20111206 67.1125 1706.841767 453.0833 送3个月会员 4G 36 会员赠送3个月 201909.0 202008.0 团队D 201909 128
3 4 56 20120412 99.0000 2872.303067 41.3500 送3个月会员 4G 35 会员赠送3个月 201909.0 202008.0 团队D 201909 91
4 5 88 20150503 88.0000 28222.901100 326.3500 送3个月会员 4G 57 会员赠送3个月 201909.0 202008.0 团队D 201909 99
16493 16494 49 20041014 49.0500 50.793967 57.2000 送3个月会员 4G 23 会员赠送3个月 201910.0 202009.0 团队D 201910 84
16494 16495 9 20060310 15.4250 554.286000 56.7667 送3个月会员 4G 47 NaN NaN NaN NaN 201911 0
16495 16496 28 20020417 64.7350 0.002900 111.8833 送3个月会员 2G 61 NaN NaN NaN NaN 201910 34
16496 16497 15 20121001 18.1750 186.963833 21.8333 送3个月会员 2G 28 NaN NaN NaN NaN 201910 34
16497 16498 19 20171103 36.2250 3839.240000 149.6667 送3个月会员 4G 37 会员赠送3个月 201910.0 202009.0 团队D 201910 63

16498 rows × 17 columns

  In [117]:

opt.shape

  Out[117]:

(16498, 17)

  In [118]:

#写入数据到excel中
dic = {'names':['jay','tom','jerry'],
       'salary':[1000,2000,3000],
      'age':[30,40,50]}
df = pd.DataFrame(data=dic,index=['a','b','c'])
df

  Out[118]:  

  names salary age
a jay 1000 30
b tom 2000 40
c jerry 3000 50

  In [119]:

df.to_excel('dic.xlsx')

   

  • 为什么需要将外部文件的数据读取加载到DataFrame表格中呢?
    • 将外部文件读取到DataFrame中,我们就可以基于DataFrame自身的特性对数据进行不同维度的运算和处理

   

sql¶

环境安装:

pip install sqlalchemy -i https://pypi.tuna.tsinghua.edu.cn/simple

pip install pymysql -i https://pypi.tuna.tsinghua.edu.cn/simple

   

  • 写入数据到数据库
    • from sqlalchemy import create_engine
    • 创建链接对象:
      • conn = create_engine(‘mysql+pymysql://root:boboadmin@127.0.0.1:3306/spider?charset=UTF8MB4’)

  In [122]:

dic = {'names':['jay','tom','jerry'],
       'salary':[1000,2000,3000],
      'age':[30,40,50]}
df = pd.DataFrame(data=dic)
df

  Out[122]:  

  names salary age
0 jay 1000 30
1 tom 2000 40
2 jerry 3000 50

  In [125]:

from sqlalchemy import create_engine
#创建一个链接对象
#mysql+pymysql://用户名:密码@ip:port/dbName?charset=UTF8MB4
conn = create_engine('mysql+pymysql://root:boboadmin@127.0.0.1:3306/new_spider?charset=UTF8MB4')
df.to_sql(name='tb_df_new',con=conn)

  Out[125]:

3

   

  • 读取数据库中的数据

  In [126]:

import pymysql 
conn = pymysql.Connect(
        host = '127.0.0.1', #数据库服务器地址
        port = 3306, #数据库端口
        user = 'root', #数据库的用户名
        password = 'boboadmin', #密码
        db = 'new_spider' #数据库名字
    )
ret = pd.read_sql('select * from dep',conn)
ret

   

/Users/zhangxiaobo/opt/arm-anaconda/anaconda3/lib/python3.9/site-packages/pandas/io/sql.py:761: UserWarning: pandas only support SQLAlchemy connectable(engine/connection) ordatabase string URI or sqlite3 DBAPI2 connectionother DBAPI2 objects are not tested, please consider using SQLAlchemy
  warnings.warn(

Out[126]:  

  id name
0 200 技术
1 201 人力资源
2 202 销售
3 203 运营

   

股票分析案例¶

  In [186]:

import pandas as pd
#可以将本地的文件数据读取到df,./data/600519.xlsx
df = pd.read_excel('data/600519.xlsx')
df.head()

  Out[186]:  

  Unnamed: 0 date open close high low volume code
0 0 2015-01-05 24.096 35.823 37.387 23.250 94515.0 600519
1 1 2015-01-06 33.532 31.560 35.860 29.914 55020.0 600519
2 2 2015-01-07 29.932 27.114 33.078 24.432 54797.0 600519
3 3 2015-01-08 28.078 26.041 28.550 24.569 40525.0 600519
4 4 2015-01-09 24.805 24.723 29.687 24.541 53982.0 600519

  In [187]:

#删除无用的一列
df.drop(columns='Unnamed: 0',inplace=True) #inplace=True将删除操作作用在了原始数据中

  In [188]:

df.shape

  Out[188]:

(2153, 7)

  In [189]:

df.head()

  Out[189]:  

  date open close high low volume code
0 2015-01-05 24.096 35.823 37.387 23.250 94515.0 600519
1 2015-01-06 33.532 31.560 35.860 29.914 55020.0 600519
2 2015-01-07 29.932 27.114 33.078 24.432 54797.0 600519
3 2015-01-08 28.078 26.041 28.550 24.569 40525.0 600519
4 2015-01-09 24.805 24.723 29.687 24.541 53982.0 600519

  In [190]:

df.info()

   

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 2153 entries, 0 to 2152
Data columns (total 7 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   date    2153 non-null   object 
 1   open    2153 non-null   float64
 2   close   2153 non-null   float64
 3   high    2153 non-null   float64
 4   low     2153 non-null   float64
 5   volume  2153 non-null   float64
 6   code    2153 non-null   int64  
dtypes: float64(5), int64(1), object(1)
memory usage: 117.9+ KB

  In [191]:

#将date列转转换成时间类型
df['date'] = df['date'].astype('datetime64') #astype用作类型转换

  In [192]:

df.info()

   

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 2153 entries, 0 to 2152
Data columns (total 7 columns):
 #   Column  Non-Null Count  Dtype         
---  ------  --------------  -----         
 0   date    2153 non-null   datetime64[ns]
 1   open    2153 non-null   float64       
 2   close   2153 non-null   float64       
 3   high    2153 non-null   float64       
 4   low     2153 non-null   float64       
 5   volume  2153 non-null   float64       
 6   code    2153 non-null   int64         
dtypes: datetime64[ns](1), float64(5), int64(1)
memory usage: 117.9 KB

  In [193]:

#显示索引优势:可以增加数据的可读性
#将date列作为表格的行索引
df.set_index('date',inplace=True)

  In [194]:

df.head()

  Out[194]:  

  open close high low volume code
date            
2015-01-05 24.096 35.823 37.387 23.250 94515.0 600519
2015-01-06 33.532 31.560 35.860 29.914 55020.0 600519
2015-01-07 29.932 27.114 33.078 24.432 54797.0 600519
2015-01-08 28.078 26.041 28.550 24.569 40525.0 600519
2015-01-09 24.805 24.723 29.687 24.541 53982.0 600519

  In [195]:

df.shape

  Out[195]:

(2153, 6)

   

  • 计算股票的每日收益率和7日波动率:通过计算收益率和波动率,我们可以评估股票的风险和收益情况。

    • 每日收益率:(当日收盘价 – 前一日的收盘价)/ 前一日的收盘价
      • shift():将一组数据向前或者前后进行移动
    • 7日波动率:对每日收益率数据进行每7日滚动的方差计算
      • rolling():设置滚动窗口

  In [196]:

df['close'].shift(1)  #前日收盘

  Out[196]:

date
2015-01-05         NaN
2015-01-06      35.823
2015-01-07      31.560
2015-01-08      27.114
2015-01-09      26.041
                ...   
2023-11-03    1779.500
2023-11-06    1811.240
2023-11-07    1812.000
2023-11-08    1791.170
2023-11-09    1798.340
Name: close, Length: 2153, dtype: float64

  In [197]:

#每日收益率:(当日收盘价 - 前一日的收盘价)/ 前一日的收盘价
day_rate = (df['close'] - df['close'].shift(1)) / df['close'].shift(1)
day_rate

  Out[197]:

date
2015-01-05         NaN
2015-01-06   -0.119002
2015-01-07   -0.140875
2015-01-08   -0.039574
2015-01-09   -0.050612
                ...   
2023-11-03    0.017836
2023-11-06    0.000420
2023-11-07   -0.011496
2023-11-08    0.004003
2023-11-09   -0.002352
Name: close, Length: 2153, dtype: float64

  In [198]:

#7日波动率
day_7_rolling_rate = day_rate.rolling(7).var() #var计算一组数据的方差
day_7_rolling_rate 

  Out[198]:

date
2015-01-05         NaN
2015-01-06         NaN
2015-01-07         NaN
2015-01-08         NaN
2015-01-09         NaN
                ...   
2023-11-03    0.000457
2023-11-06    0.000442
2023-11-07    0.000513
2023-11-08    0.000510
2023-11-09    0.000525
Name: close, Length: 2153, dtype: float64

   

  • 查找股票的市值最大和最小日
    • 市值 = 收盘价 * 成交量
    • 找出市值数据中最大最小值下标(市值最大和最小日期)
      • idxmax() & idxmin()

  In [199]:

#每日市值
day_values = df['close'] * df['volume']
day_values

  Out[199]:

date
2015-01-05    3.385811e+06
2015-01-06    1.736431e+06
2015-01-07    1.485766e+06
2015-01-08    1.055312e+06
2015-01-09    1.334597e+06
                  ...     
2023-11-03    5.465598e+07
2023-11-06    4.624949e+07
2023-11-07    3.507469e+07
2023-11-08    2.615865e+07
2023-11-09    2.296461e+07
Length: 2153, dtype: float64

  In [200]:

#找出市值数据中最大最小值下标(市值最大和最小日期)
day_values.idxmax() #求最大元素下标

  Out[200]:

Timestamp('2021-09-27 00:00:00')

  In [201]:

day_values.idxmin() #求最小元素下标

  Out[201]:

Timestamp('2015-02-02 00:00:00')

   

  • 输出该股票所有收盘比开盘上涨3%以上的日期
    • (收盘 – 开盘) / 开盘 > 0.03

  In [202]:

ex = (df['close'] - df['open']) / df['open']  > 0.03
ex #想获取所有True对应的索引

  Out[202]:

date
2015-01-05     True
2015-01-06    False
2015-01-07    False
2015-01-08    False
2015-01-09    False
              ...  
2023-11-03    False
2023-11-06    False
2023-11-07    False
2023-11-08    False
2023-11-09    False
Length: 2153, dtype: bool

  In [203]:

#在DataFrame中,可以使用布尔值作为表格的行索引:就会保留True对应的行数据,忽略False对应的行数据
df.loc[ex] #取出了True对应的行数据(满足要求的行数据)

  Out[203]:  

  open close high low volume code
date            
2015-01-05 24.096 35.823 37.387 23.250 94515.0 600519
2015-01-15 18.887 20.869 21.169 17.605 48585.0 600519
2015-01-20 11.732 13.605 15.805 8.987 61022.0 600519
2015-01-21 13.778 17.496 17.987 12.805 52674.0 600519
2015-01-23 15.460 16.278 18.332 15.450 33084.0 600519
2022-11-15 1484.179 1540.179 1551.149 1473.179 56318.0 600519
2023-01-05 1711.089 1775.089 1775.089 1707.089 47943.0 600519
2023-02-20 1795.089 1849.089 1852.889 1791.289 29669.0 600519
2023-05-22 1664.099 1720.089 1726.089 1664.089 41284.0 600519
2023-07-28 1832.000 1897.000 1900.000 1828.010 39018.0 600519

252 rows × 6 columns

  In [204]:

df.loc[ex].index #获取了满足要求行数据的行索引

  Out[204]:

DatetimeIndex(['2015-01-05', '2015-01-15', '2015-01-20', '2015-01-21',
               '2015-01-23', '2015-01-26', '2015-02-03', '2015-02-09',
               '2015-02-11', '2015-02-16',
               ...
               '2022-06-10', '2022-06-17', '2022-08-31', '2022-11-01',
               '2022-11-04', '2022-11-15', '2023-01-05', '2023-02-20',
               '2023-05-22', '2023-07-28'],
              dtype='datetime64[ns]', name='date', length=252, freq=None)

   

  • 假如张三从2015年1月1日开始,每月第一个交易日买入1手股票,每年最后一个交易日卖出所有股票,到今天为止,我的收益如何?

    • 分析:
      • 买入股票
        • 一个完整的年,需要买入12手1200支股票。以购买当期的开盘价进行股票的买卖。
      • 卖出股票
        • 一个完整的年,需要卖出1200支股票(收盘价为单价)
      • 特殊情况:
        • 最后一年就是一个特殊的年(因为没有到该年最后一个交易日),只可以买不可以卖,但是手里剩余的股票是需要计算到总收益中。
    • resample函数介绍:pandas库中的resample函数主要用于将时间序列数据重新采样到不同的时间频率,例如从按天采样重新采样为按周或按月采样。resample函数的常用语法如下:
      • df.resample(rule, …).func()
      • 其中,df是一个时间序列数据的DataFrame,rule是指定重采样频率的规则字符串(H小时、W星期、M月、A年等),func是用于聚合数据的函数(例如求和、平均值等)。例如:
        • df.resample(‘H’).mean()
        • df.resample(‘W’).sum()
        • df.resample(‘M’).max()

   

  • 分析计算张三买入股票一共花了多少钱?

  In [215]:

#找出每个月的第一个交易日的开盘价
monthly = df.resample('M').first() #取出了每个月第一个交易日对应的行数据
monthly.head(5)
#获取的数据会发现日期是每月最后一天的日期并不是第一个交易日的日期?(无需解决,自身存在的bug),但是行数据是没错

  Out[215]:  

  open close high low volume code
date            
2015-01-31 24.096 35.823 37.387 23.250 94515.0 600519
2015-02-28 11.269 10.641 12.078 9.441 33983.0 600519
2015-03-31 25.169 25.105 27.896 23.532 31098.0 600519
2015-04-30 29.923 29.296 31.314 28.514 76875.0 600519
2015-05-31 81.405 83.505 87.169 79.005 54739.0 600519

  In [216]:

#买入股票的总花费
total_cost = monthly['open'].sum() * 100
total_cost

  Out[216]:

10173374.9

   

  • 卖出股票到手多少钱?

  In [219]:

yearly = df.resample('A').last() #A表示年
yearly

  Out[219]:  

  open close high low volume code
date            
2015-12-31 73.910 73.880 75.190 73.510 19673.0 600519
2016-12-31 188.471 196.011 197.151 188.471 34687.0 600519
2017-12-31 586.648 566.138 595.148 560.248 76038.0 600519
2018-12-31 442.947 469.657 476.047 439.647 63678.0 600519
2019-12-31 1077.186 1077.186 1082.186 1070.696 22588.0 600519
2020-12-31 1852.211 1909.211 1910.191 1850.211 38860.0 600519
2021-12-31 2000.504 1980.504 2003.484 1958.504 29665.0 600519
2022-12-31 1710.089 1701.089 1727.079 1701.089 25333.0 600519
2023-12-31 1790.110 1794.110 1799.000 1783.000 12800.0 600519

  In [220]:

recv = yearly['close'].sum() * 1200
recv

  Out[220]:

11721343.2

  In [221]:

#计算总收益
recv - total_cost

  Out[221]:

1547968.2999999989

   

数据清洗¶

概述¶

数据清洗是指对原始数据进行处理和转换,以去除无效、重复、缺失或错误的数据,使数据符合分析的要求。

作用和意义¶

  • 提高数据质量:
    • 通过数据清洗,数据质量得到提升,减少错误分析和错误决策。
  • 增加数据可用性:
    • 清洗后的数据更加规整和易于使用,提高数据的可用性和可读性。

清洗维度¶

  • 缺失值处理:
    • 对于缺失的数据,可以删除包含缺失值的行或列或者填充缺失值。
  • 重复值处理:
    • 识别和删除重复的数据行,避免重复数据对分析结果产生误导。
  • 异常值处理:
    • 检测和处理异常值,决定是删除、替换或保留异常值。

缺失值清洗¶

缺失值/空值的删除¶
  • 伪造缺失值数据

  In [222]:

import pandas as pd
from pandas import DataFrame,Series

df = pd.read_csv('./data/none.csv',index_col=0)
df #NAN就是None空白

  Out[222]:  

  0 1 2 3 4
0 22 6 44.0 NaN 11
1 98 88 20.0 85.0 16
2 19 83 NaN 84.0 46
3 93 64 76.0 NaN 85
4 7 63 20.0 21.0 45
5 36 19 36.0 NaN 82
6 53 98 7.0 89.0 1

   

  • 缺失值的检测和删除,相关方法:
    • isnull():检测df中的每一个元素是否为空值,为空则给该元素返回True,否则返回False
    • notnull():检测df中的每一个元素是否为非空值,为非空则给该元素返回True,否则返回False
    • any():检测一行或一列布尔值中是否存在一个或多个True,有则返回True,否则返回False
    • all():检测一行或一列布尔值中是否存全部为True,有则返回True,否则返回False
    • dropna():将存在缺失值/空值的行或者列进行删除

  In [223]:

#检测哪些列中存在空值
df.isnull()

  Out[223]:  

  0 1 2 3 4
0 False False False True False
1 False False False False False
2 False False True False False
3 False False False True False
4 False False False False False
5 False False False True False
6 False False False False False

  In [224]:

df.notnull()

  Out[224]:  

  0 1 2 3 4
0 True True True False True
1 True True True True True
2 True True False True True
3 True True True False True
4 True True True True True
5 True True True False True
6 True True True True True

  In [226]:

#可以判定哪些列中存在空值
df.isnull().any(axis=0) 
#axis=0表示针对列进行any操作
#axis=1表示针对行进行any操作

  Out[226]:

0    False
1    False
2     True
3     True
4    False
dtype: bool

  In [228]:

df.notnull().all(axis=0)

  Out[228]:

0     True
1     True
2    False
3    False
4     True
dtype: bool

   

  • dropna()进行空值检测和过滤

  In [240]:

df.dropna() #直接返回删除空值对应行后的结果,不会直接改变原始数据

  Out[240]:  

  0 1 2 3 4
1 98 88 20.0 85.0 16
4 7 63 20.0 21.0 45
6 53 98 7.0 89.0 1

   

  • 计算df中每一列存在缺失值的个数和占比

  In [238]:

for col in df.columns:
    #满足该条件则表示第col列中是存在空值
    if df[col].isnull().sum() > 0:
        #求出了该列空值的个数
        null_count = df[col].isnull().sum()
        #求出该列中空值的占比:空值的数量/列的总元素个数
        p = format(null_count / df[col].size,'.2%')
        print(col,null_count,p)     

   

2 1 14.29%
3 3 42.86%

   

  • 缺失值/空值的填充
      • fillna(value,method,axis)
    • 参数介绍:
      • value:给空值填充的值
      • method:填充方式,可以为bfill向后填充和ffill向前填充
      • axis:填充轴向

   

  • 使用任意值填充空值

  In [245]:

df.fillna(value=666)

  Out[245]:  

  0 1 2 3 4
0 22 6 44.0 666.0 11
1 98 88 20.0 85.0 16
2 19 83 666.0 84.0 46
3 93 64 76.0 666.0 85
4 7 63 20.0 21.0 45
5 36 19 36.0 666.0 82
6 53 98 7.0 89.0 1

   

  • 使用近邻值填充空值

  In [249]:

df.fillna(axis=0,method='ffill').fillna(axis=0,method='bfill') #bfill
#在竖直方向上,会用空前面的值填充空值

  Out[249]:  

  0 1 2 3 4
0 22 6 44.0 85.0 11
1 98 88 20.0 85.0 16
2 19 83 20.0 84.0 46
3 93 64 76.0 84.0 85
4 7 63 20.0 21.0 45
5 36 19 36.0 21.0 82
6 53 98 7.0 89.0 1

   

  • 使用相关的统计值填充空值

  In [251]:

#可以使用空值列的均值、中位数等统计指标对空值进行填充
for col in df.columns:
    if df[col].isnull().sum() > 0:
        #计算出空值列对应的均值
        mean_value = df[col].mean()
        df[col].fillna(value=mean_value,inplace=True)

  In [252]:

df

  Out[252]:  

  0 1 2 3 4
0 22 6 44.000000 69.75 11
1 98 88 20.000000 85.00 16
2 19 83 33.833333 84.00 46
3 93 64 76.000000 69.75 85
4 7 63 20.000000 21.00 45
5 36 19 36.000000 69.75 82
6 53 98 7.000000 89.00 1

   

注意:实现空值的清洗最好选择删除的方式,如果删除的成本比较高,再选择填充的方式。

   

重复值清洗¶

  • 伪造重复行的数据源

  In [253]:

df = pd.read_csv('data/repeat.csv',index_col=0)
df

  Out[253]:  

  0 1 2 3 4
0 7 68 20 14 95
1 70 85 37 72 86
2 79 6 92 24 5
3 0 0 0 0 0
4 56 46 25 14 49
5 0 0 0 0 0
6 66 28 98 14 1
7 0 0 0 0 0

   

  • 使用duplicated()方法检测重复的行数据

  In [255]:

df.duplicated().sum()

  Out[255]:

2

   

  • 使用drop_duplicates()方法检测且删除重复的行数据

  In [256]:

df.drop_duplicates()

  Out[256]:  

  0 1 2 3 4
0 7 68 20 14 95
1 70 85 37 72 86
2 79 6 92 24 5
3 0 0 0 0 0
4 56 46 25 14 49
6 66 28 98 14 1

   

异常值清洗¶

异常值是分析师和数据科学家常用的术语,因为它需要密切注意,否则可能导致错误的估计。 简单来说,异常值是一个观察值,远远超出了样本中的整体模式。

异常值在统计学上的全称是疑似异常值,也称作离群点,异常值的分析也称作离群点分析。异常值是指样本中出现的“极端值”,数据值看起来异常大或异常小,其分布明显偏离其余的观测值。异常值分析是检验数据中是否存在不合常理的数据。

  • 给定条件的异常数据处理
    • 自定义一个1000行3列(A,B,C)取值范围为0-1的数据源,然后将C列中的值大于其两倍标准差的异常值进行清洗

  In [257]:

data = pd.read_csv('./data/outlier.csv',index_col=0)
data

  Out[257]:  

  A B C
0 0.794514 0.337913 0.299290
1 0.596259 0.512930 0.554369
2 0.115003 0.401490 0.669573
3 0.773007 0.547263 0.780857
4 0.469255 0.316957 0.214900
995 0.650119 0.042532 0.405112
996 0.704271 0.317155 0.779764
997 0.138225 0.493625 0.152215
998 0.273130 0.763846 0.031242
999 0.536671 0.674845 0.004224

1000 rows × 3 columns

  In [261]:

#C列的2倍标准差
twice_std = data['C'].std() * 2
twice_std

  Out[261]:

0.5705417437083701

  In [267]:

#判定异常值
ex = data['C'] > twice_std
ex #True表示为异常值,False表示正常值

  Out[267]:

0      False
1      False
2       True
3       True
4      False
       ...  
995    False
996     True
997    False
998    False
999    False
Name: C, Length: 1000, dtype: bool

  In [268]:

data.loc[ex] #取出了True对应的行数据(异常值对应的行数据)

  Out[268]:  

  A B C
2 0.115003 0.401490 0.669573
3 0.773007 0.547263 0.780857
7 0.013230 0.419507 0.960728
8 0.858091 0.805964 0.586865
10 0.158810 0.095586 0.775476
981 0.803646 0.791588 0.782859
989 0.534287 0.734984 0.701372
991 0.258987 0.039801 0.751450
993 0.002957 0.939943 0.673207
996 0.704271 0.317155 0.779764

424 rows × 3 columns

  In [269]:

drop_indexs = data.loc[ex].index #提取了异常值对应行数据的行索引
drop_indexs

  Out[269]:

Int64Index([  2,   3,   7,   8,  10,  11,  13,  14,  20,  21,
            ...
            964, 965, 972, 975, 978, 981, 989, 991, 993, 996],
           dtype='int64', length=424)

  In [270]:

#将异常值对应的行从数据表格中进行删除
data.drop(index=drop_indexs)

  Out[270]:  

  A B C
0 0.794514 0.337913 0.299290
1 0.596259 0.512930 0.554369
4 0.469255 0.316957 0.214900
5 0.539357 0.107476 0.187495
6 0.385599 0.561930 0.377683
994 0.494248 0.558101 0.128541
995 0.650119 0.042532 0.405112
997 0.138225 0.493625 0.152215
998 0.273130 0.763846 0.031242
999 0.536671 0.674845 0.004224

576 rows × 3 columns

   

map映射¶

  • 映射就是指给一组数据中的每一个元素绑定一个固定的数据

  In [283]:

df = pd.read_csv('./data/map.csv').drop(columns='Unnamed: 0')
df

  Out[283]:  

  name salary
0 张三 10000
1 李四 15000
2 王五 21000
3 张三 10000

  In [286]:

#给每个人起一个英文名,将其作为表格中新的一列存在
dic = {
    '张三':'Tom',
    '李四':'Jerry',
    '王五':'Jay'
}#映射关系表
df['ename'] = df['name'].map(dic)
df

  Out[286]:  

  name salary ename
0 张三 10000 Tom
1 李四 15000 Jerry
2 王五 21000 Jay
3 张三 10000 Tom

   

map充当运算工具¶

  In [289]:

#将每一个人的税后薪资进行计算:超过5000部分的钱需要缴纳25%的税
def after_sal(s): #参数s就依次表示每一个人的薪资数据
    return s - (s-5000)*0.25
df['after_sal'] = df['salary'].map(after_sal)
df

  Out[289]:  

  name salary ename after_sal
0 张三 10000 Tom 8750.0
1 李四 15000 Jerry 12500.0
2 王五 21000 Jay 17000.0
3 张三 10000 Tom 8750.0

   

排序¶

  In [280]:

data = pd.read_csv('./data/outlier.csv',index_col=0)
data.head()

  Out[280]:  

  A B C
0 0.794514 0.337913 0.299290
1 0.596259 0.512930 0.554369
2 0.115003 0.401490 0.669573
3 0.773007 0.547263 0.780857
4 0.469255 0.316957 0.214900

  In [281]:

data.sort_values(by='C') #默认根据C列中的元素从小到大进行排序

  Out[281]:  

  A B C
647 0.102826 0.268895 0.000036
521 0.491587 0.767086 0.000680
599 0.560323 0.884960 0.001386
17 0.475333 0.968809 0.002639
717 0.561099 0.596751 0.002810
913 0.575918 0.155275 0.995703
91 0.914415 0.738960 0.996564
273 0.746750 0.470466 0.996640
67 0.803291 0.959692 0.996780
329 0.728317 0.810622 0.998517

1000 rows × 3 columns

  In [282]:

data.sort_values(by='C',ascending=False)  #从大到小排序

  Out[282]:  

  A B C
329 0.728317 0.810622 0.998517
67 0.803291 0.959692 0.996780
273 0.746750 0.470466 0.996640
91 0.914415 0.738960 0.996564
913 0.575918 0.155275 0.995703
717 0.561099 0.596751 0.002810
17 0.475333 0.968809 0.002639
599 0.560323 0.884960 0.001386
521 0.491587 0.767086 0.000680
647 0.102826 0.268895 0.000036

1000 rows × 3 columns

  In [292]:

#axis=0表示的行,axis=1表示的是列
data.sort_index(axis=1,ascending=False)

  Out[292]:  

  C B A
0 0.299290 0.337913 0.794514
1 0.554369 0.512930 0.596259
2 0.669573 0.401490 0.115003
3 0.780857 0.547263 0.773007
4 0.214900 0.316957 0.469255
995 0.405112 0.042532 0.650119
996 0.779764 0.317155 0.704271
997 0.152215 0.493625 0.138225
998 0.031242 0.763846 0.273130
999 0.004224 0.674845 0.536671

1000 rows × 3 columns

  In [295]:

#手动对列索引进行排列,此处indices表示排列的结果(只能用隐式索引)
#axis=0表示的行,axis=1表示的是列
data.take(indices=[1,0,2],axis=1)

  Out[295]:  

  B A C
0 0.337913 0.794514 0.299290
1 0.512930 0.596259 0.554369
2 0.401490 0.115003 0.669573
3 0.547263 0.773007 0.780857
4 0.316957 0.469255 0.214900
995 0.042532 0.650119 0.405112
996 0.317155 0.704271 0.779764
997 0.493625 0.138225 0.152215
998 0.763846 0.273130 0.031242
999 0.674845 0.536671 0.004224

1000 rows × 3 columns

   

map运算¶

  In [277]:

#计算下面表格中每个人的税后薪资:超过3000部分的钱缴纳50%的税,计算每个人的税后薪资
#加载数据
df = pd.read_csv('./data/fruits.csv').drop(columns='Unnamed: 0')
df

  Out[277]:  

  item price color weight
0 Apple 4.0 red 12
1 Banana 3.0 yellow 20
2 Orange 3.0 yellow 50
3 Banana 2.5 green 30
4 Orange 4.0 green 20
5 Apple 2.0 green 44

   

分组聚合¶

   

  • 数据分类处理的核心:
    • groupby()函数
    • groups属性查看分组情况

  In [296]:

#加载数据
df = pd.read_csv('./data/fruits.csv').drop(columns='Unnamed: 0')
df

  Out[296]:  

  item price color weight
0 Apple 4.0 red 12
1 Banana 3.0 yellow 20
2 Orange 3.0 yellow 50
3 Banana 2.5 green 30
4 Orange 4.0 green 20
5 Apple 2.0 green 44

  In [298]:

#想根据不同水果种类对数据进行分组
df.groupby(by='item').groups #使用groupby分组后,调用groups查看分组的结果

  Out[298]:

{'Apple': [0, 5], 'Banana': [1, 3], 'Orange': [2, 4]}

  In [300]:

#计算不同水果的平均价格
df.groupby(by='item')['price'] #单独取出每组数据的价格数据
mean_price = df.groupby(by='item')['price'].mean()
mean_price

  Out[300]:

item
Apple     3.00
Banana    2.75
Orange    3.50
Name: price, dtype: float64

  In [304]:

mean_price.to_dict()

  Out[304]:

{'Apple': 3.0, 'Banana': 2.75, 'Orange': 3.5}

  In [303]:

#将每种水果的平均价格汇总到原始表格中
dic = {
    'Apple':3.00,
    'Banana':2.75,
    'Orange':3.50
}
#dic = mean_price.to_dict()

df['mean_price'] = df['item'].map(dic)
df

  Out[303]:  

  item price color weight mean_price
0 Apple 4.0 red 12 3.00
1 Banana 3.0 yellow 20 2.75
2 Orange 3.0 yellow 50 3.50
3 Banana 2.5 green 30 2.75
4 Orange 4.0 green 20 3.50
5 Apple 2.0 green 44 3.00

  In [311]:

#计算不同颜色水果的最大重量
color_max_weight = df.groupby(by='color')['weight'].max()
color_max_weight

  Out[311]:

color
green     44
red       12
yellow    50
Name: weight, dtype: int64

  In [312]:

df['max_weight'] = df['color'].map(color_max_weight.to_dict())
df

  Out[312]:  

  item price color weight mean_price max_weight
0 Apple 4.0 red 12 3.00 12
1 Banana 3.0 yellow 20 2.75 50
2 Orange 3.0 yellow 50 3.50 50
3 Banana 2.5 green 30 2.75 44
4 Orange 4.0 green 20 3.50 44
5 Apple 2.0 green 44 3.00 44

   

  • 对分组后的结果进行多种不同形式的聚合操作

  In [315]:

#求每种水果的平均价格和最高价格、最低价格
df.groupby(by='item')['price'].agg(['mean','max','min'])

  Out[315]:  

  mean max min
item      
Apple 3.00 4.0 2.0
Banana 2.75 3.0 2.5
Orange 3.50 4.0 3.0

   

透视表¶

透视表是一种可以对数据动态排布并且分类汇总的表格格式。或许大多数人都在Excel使用过数据透视表,也体会到它的强大功能,而在pandas中它被称作pivot_table。

  In [317]:

df = pd.read_csv('./data/透视表-篮球赛.csv')  
df.head(3)

  Out[317]:  

  对手 胜负 主客场 命中 投篮数 投篮命中率 3分命中率 篮板 助攻 得分
0 勇士 10 23 0.435 0.444 6 11 27
1 国王 8 21 0.381 0.286 3 9 27
2 小牛 10 19 0.526 0.462 3 7 29

  In [319]:

#根据胜负字段进行数据的分组,然后对每组数据进行均值计算
df.pivot_table(index='对手',aggfunc='mean')

  Out[319]:  

  3分命中率 助攻 命中 得分 投篮命中率 投篮数 篮板
对手              
76人 0.33950 10.00 9.0 28.00 0.4405 20.5 3.5
勇士 0.44400 11.00 10.0 27.00 0.4350 23.0 6.0
国王 0.28600 9.00 8.0 27.00 0.3810 21.0 3.0
太阳 0.54500 7.00 12.0 48.00 0.5450 22.0 2.0
小牛 0.46200 7.00 10.0 29.00 0.5260 19.0 3.0
尼克斯 0.36900 9.50 10.5 34.00 0.4175 25.0 3.5
开拓者 0.57100 3.00 16.0 48.00 0.5520 29.0 8.0
掘金 0.14300 9.00 6.0 21.00 0.3750 16.0 8.0
步行者 0.29150 12.50 8.5 27.50 0.3965 21.5 6.5
湖人 0.44400 9.00 13.0 36.00 0.5910 22.0 4.0
灰熊 0.35025 7.75 8.5 27.25 0.4015 21.0 4.5
爵士 0.60400 8.00 13.5 42.50 0.5905 22.0 3.5
猛龙 0.27300 11.00 8.0 38.00 0.3200 25.0 6.0
篮网 0.61500 8.00 13.0 37.00 0.6500 20.0 10.0
老鹰 0.54500 11.00 8.0 29.00 0.5330 15.0 3.0
骑士 0.42900 13.00 8.0 35.00 0.3810 21.0 11.0
鹈鹕 0.40000 17.00 8.0 26.00 0.5000 16.0 1.0
黄蜂 0.40000 11.00 8.0 27.00 0.4440 18.0 10.0

  In [323]:

#根据胜负字段进行数据的分组,对分组中的篮板和得分两个字段进行求和运算
df.pivot_table(index='胜负',values=['篮板','得分'],aggfunc='sum')

  Out[323]:  

  得分 篮板
胜负    
692 108
109 19

  In [322]:

#根据主客场字段进行数据分类后,对分类后的得分字段求最大值、篮板字段求均值和助攻字段求累加和操作
df.pivot_table(index='主客场',aggfunc={'得分':'max','篮板':'mean','助攻':'sum'})

  Out[322]:  

  助攻 得分 篮板
主客场      
121 56 5.333333
116 48 4.846154

  In [324]:

#获取所有队主客场的总得分
df.pivot_table(index='主客场',values='得分',aggfunc='sum')

  Out[324]:  

  得分
主客场  
397
404

  In [326]:

#查看主客场下的总得分都是哪些具体球队的得分构成的
df.pivot_table(index='主客场',values='得分',aggfunc='sum',columns='对手')

  Out[326]:  

对手 76人 勇士 国王 太阳 小牛 尼克斯 开拓者 掘金 步行者 湖人 灰熊 爵士 猛龙 篮网 老鹰 骑士 鹈鹕 黄蜂
主客场                                    
29.0 NaN NaN NaN 29.0 37.0 NaN 21.0 29.0 NaN 60.0 56.0 38.0 37.0 NaN 35.0 26.0 NaN
27.0 27.0 27.0 48.0 NaN 31.0 48.0 NaN 26.0 36.0 49.0 29.0 NaN NaN 29.0 NaN NaN 27.0

  In [327]:

#查看主客场下的总得分都是哪些具体球队的得分构成的
df.pivot_table(index='主客场',values='得分',aggfunc='sum',columns='对手',fill_value=0)

  Out[327]:  

对手 76人 勇士 国王 太阳 小牛 尼克斯 开拓者 掘金 步行者 湖人 灰熊 爵士 猛龙 篮网 老鹰 骑士 鹈鹕 黄蜂
主客场                                    
29 0 0 0 29 37 0 21 29 0 60 56 38 37 0 35 26 0
27 27 27 48 0 31 48 0 26 36 49 29 0 0 29 0 0 27

  In [330]:

#多条件分类汇总操作
df.pivot_table(index=['主客场','对手'],values='得分',aggfunc='sum')

  Out[330]:  

    得分
主客场 对手  
76人 29
小牛 29
尼克斯 37
掘金 21
步行者 29
灰熊 60
爵士 56
猛龙 38
篮网 37
骑士 35
鹈鹕 26
76人 27
勇士 27
国王 27
太阳 48
尼克斯 31
开拓者 48
步行者 26
湖人 36
灰熊 49
爵士 29
老鹰 29
黄蜂 27

   

  • 快捷键:
    • 增加cell:a,b
    • 删除cell:x
    • 运行cell:shift+enter

   

今日重点:数据清洗、map映射和map充当运算工具、groupby分组聚合、pivot_table透视¶

  In [ ]:

pdf有表格  pandas+。。。

   

手机销量分析案例¶

  • 巩固分组聚合操作

  In [46]:

#加载数据
import pandas as pd
data = pd.read_excel('./data/Phone.xlsx')

  In [47]:

#缺失值处理

  In [48]:

#查看不同品牌手机的累计销量和累计销售额,且对累计销量进行降序

  In [49]:

#查看不同月份的销量情况,哪些月份销量比较高

  In [50]:

#不同年龄段的购买力

  In [51]:

#查看不同城市的购买力情况

  In [52]:

#查看不同品牌的不同型号的最高和最低价格是多少

   

美国大选政治现金分析:

  • 加载数据
  • 查看数据的基本信息
  • 指定数据截取,将如下字段的数据进行提取,其他数据舍弃
    • cand_nm :候选人姓名
    • contbr_nm : 捐赠人姓名
    • contbr_st :捐赠人所在州
    • contbr_employer : 捐赠人所在公司
    • contbr_occupation : 捐赠人职业
    • contb_receipt_amt :捐赠数额(美元)
    • contb_receipt_dt : 捐款的日期
  • 对新数据进行总览,查看是否存在缺失数据
  • 用统计学指标快速描述数值型属性的概要。
  • 空值处理。可能因为忘记填写或者保密等等原因,相关字段出现了空值,将其填充为NOT PROVIDE
  • 异常值处理。将捐款金额<=0的数据删除
  • 新建一列为各个候选人所在党派party
  • 查看party这一列中有哪些不同的元素
  • 统计party列中各个元素出现次数
  • 查看各个党派收到的政治献金总数contb_receipt_amt
  • 查看具体每天各个党派收到的政治献金总数contb_receipt_amt
  • 将表中日期格式转换为’yyyy-mm-dd’。
  • 查看老兵(捐献者职业)DISABLED VETERAN主要支持谁

  In [11]:

parties = {
  'Bachmann, Michelle': 'Republican',
  'Romney, Mitt': 'Republican',
  'Obama, Barack': 'Democrat',
  "Roemer, Charles E. 'Buddy' III": 'Reform',
  'Pawlenty, Timothy': 'Republican',
  'Johnson, Gary Earl': 'Libertarian',
  'Paul, Ron': 'Republican',
  'Santorum, Rick': 'Republican',
  'Cain, Herman': 'Republican',
  'Gingrich, Newt': 'Republican',
  'McCotter, Thaddeus G': 'Republican',
  'Huntsman, Jon': 'Republican',
  'Perry, Rick': 'Republican'           
 }
months = {'JAN' : 1, 'FEB' : 2, 'MAR' : 3, 'APR' : 4, 'MAY' : 5, 'JUN' : 6,
          'JUL' : 7, 'AUG' : 8, 'SEP' : 9, 'OCT': 10, 'NOV': 11, 'DEC' : 12}

  In [10]:

#加载数据:usa_election.txt
df = pd.read_csv('./data/usa_election.txt').drop(columns='Unnamed: 0')
df.head()

  Out[10]:  

  cand_nm contbr_nm contbr_st contbr_employer contbr_occupation contb_receipt_amt contb_receipt_dt
0 Bachmann, Michelle HARVEY, WILLIAM AL RETIRED RETIRED 250.0 20-JUN-11
1 Bachmann, Michelle HARVEY, WILLIAM AL RETIRED RETIRED 50.0 23-JUN-11
2 Bachmann, Michelle SMITH, LANIER AL INFORMATION REQUESTED INFORMATION REQUESTED 250.0 05-JUL-11
3 Bachmann, Michelle BLEVINS, DARONDA AR NONE RETIRED 250.0 01-AUG-11
4 Bachmann, Michelle WARDENBURG, HAROLD AR NONE RETIRED 300.0 20-JUN-11

   

Matplotlib绘图操作¶

   

  • 在数据分析中画图的意义:
    • 1.可以将相关的分析结论进行可视化的展示
    • 2.通过画图的操作对相关的数据进行探索

  In [135]:

import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['PingFang HK'] #mac系统使用
# plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']# windows使用设置微软雅黑字体

   

  • 线形图
    • 用于显示数据随变量的变化趋势

  In [53]:

df = pd.read_csv('data/CD_Sale.csv').drop(columns='Unnamed: 0')

  In [54]:

#所有用户每月的消费总次数

  In [55]:

#统计每月的消费人数

   

  • 散点图
    • 用于展示两个数值变量之间的关系

  In [56]:

#查看每个用户的总消费金额和总消费产品数量之间的关系

   

  • 直方图
    • 用于展示一组数据密度的分布情况。它将数据划分为多个相邻的区间,并计算每个区间内数据的频数或频率,然后将这些频数或频率表示为纵向的矩形条,从而形成一个条形图。

  In [57]:

#查看每个用户消费次数的分布情况

   

  • 柱状图:
    • 用于展示不同类别或组的数据之间的比较和关系

  In [58]:

GDP = [36102,38700,14083,25002]
city = ['Beijing','Shanghai','Tianjin','Chongqing']

   

  • 饼图
    • 饼图可以显示不同类别或组成部分在整体中的占比,用于传达数据的分布和比例关系。

  In [59]:

#简单的饼图
education = [9823, 5601, 3759, 1400, 450]
labels = ['小学', '初中', '高中', '大学', '研究生及以上']

来源链接:https://www.cnblogs.com/fuminer/p/18823565

© 版权声明
THE END
支持一下吧
点赞8 分享
评论 抢沙发
头像
请文明发言!
提交
头像

昵称

取消
昵称表情代码快捷回复

    暂无评论内容