随笔 - 756  文章 - 0 评论 - 33 阅读 - 136万
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

1、了解Numpy与Pandas的不同

2、说明Pandas的Series与Dataframe两种结构的区别。

3、了解Pandas的Multilndex与panel结构。

4、应用Pandas实现基本数据操作

5、应用Pandas实现数据的合并

6、应用crosstab和pivot_table实现交叉表与透视表

7、应用groupby和聚合函数实现数据的分组与聚合

8、了解Pandas的plot画图功能。

9、应用Pandas实现数据的读取和存储

pandas官方文档链接:http://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html

 

一、pandas的介绍

 

 • 2008年WesMcKinney开发出的库
 • 专门用于数据挖掘的开源python库
 • 以Numpy为基础,借力Numpy模块在计算方面性能高的优势
 • 基于matplotlib,能够简便的画图
 • 独特的数据结构

为什么使用Pandas?

Numpy已经能够帮助我们处理数据,能够结合matplotlib解决部分数据展示等问题,那么pandas学习的目的在什么地方呢?

(1)、增强图表可读性

回忆我们在numpy当中创建学生成绩表样式:

复制代码
array([[9255785050],
[7176504896],
[4584785168]
[81,91565476]
[8666776795]
[4686566199],
[4695444656]
[8050456557],
[41,93904197],
[6583575740]])
复制代码

如果数据展示为这样,可读性就会更友好:

(2)、便捷的数据处理能力

可以通过一行代码将NaN修改过来

(3)、读取文件方便

(4)、封装了matplotlib、numpy的画图和计算

二、Pandas数据结构

Pandas中一共有三种数据结构,分别为:Series、DataFrame和Multilndex(老版本中叫Panel)

其中Series是一维数据结构,DataFrame是二维的表格型数据结构,Multiindex是三维的数据结构。

1、Series

Series是一个类似于一维数组的数据结构,它能够保存任何类型的数据,比如整数、字符串、浮点数等,主要由一组数据和与之相关的索引两部分构成。

Series的创建

#导入pandas
import pandas as pd
pd.Series(data=None,index=None,dtype=None)

参数:

  data:传入的数据,可以是ndarray、list等
  index:索引,必须是唯一的,且与数据的长度相等。如果没有传入索引参数,则默认会自动创建一个从0-N的整数索引。
  dtype:数据的类型

通过已有数据创建

(1)、指定内容,默认索引

#导入pandas
import pandas as pd
import numpy as np
pd.Series(data=None,index=None,dtype=None)
pd.Series(np.arange(10))

结果:

复制代码
0    0
1    1
2    2
3    3
4    4
5    5
6    6
7    7
8    8
9    9
dtype: int32
复制代码

前面是索引,后面是值

(2)、指定索引

#导入pandas
import pandas as pd
pd.Series([6.7,5.6,3,10,2],index=[1,2,3,4,5])

结果:

1     6.7
2     5.6
3     3.0
4    10.0
5     2.0
dtype: float64

(3)、通过字典数据创建

import pandas as pd
color_count = pd.Series({'red':100,'blue':200, 'green': 500, 'yellow':1000})
color_count

结果:

red        100
blue       200
green      500
yellow    1000
dtype: int64

Series的属性

为了更方便地操作Series对象中的索引和数据,Series中提供了两个属性index和values

(1)、index

import pandas as pd
color_count = pd.Series({'red':100,'blue':200, 'green': 500, 'yellow':1000})
color_count.index

结果:Index(['red', 'blue', 'green', 'yellow'], dtype='object')

(2)、values

import pandas as pd
color_count = pd.Series({'red':100,'blue':200, 'green': 500, 'yellow':1000})
color_count.values

结果:array([ 100, 200, 500, 1000], dtype=int64)

也可以使用索引来获取数据:

import pandas as pd
color_count = pd.Series({'red':100,'blue':200, 'green': 500, 'yellow':1000})
color_count[2]

结果:500

2、DataFrame

DataFrame是一个类似于二维数组或表格(如excel)的对象,既有行索引,又有列索引

 • 行索引,表明不同行,横向索引,叫index,0轴,axis=0
 • 列索引,表名不同列,纵向索引,叫columns,1轴,axis=1

DataFrame的创建

#导入pandas
import pandas as pd
pd.DataFrame(data=None,index=None,columns=None)

(1)、参数:

  index:行标签。如果没有传入索引参数,则默认会自动创建一个从0-N的整数索引。

  columns:列标签。如果没有传入索引参数,则默认会自动创建一个从0-N的整数索引

(2)、通过已有数据创建

#导入pandas
import pandas as pd
pd.DataFrame(np.random.randn(2,3))

结果:

 回忆咱们在前面直接使用np创建的数组显示方式,比较两者的区别。

举例二:创建学生成绩表

import numpy as np
# 生成10名同学,5门功课的数据
score =np.random.randint(40,100,(10,5))
score

结果:

复制代码
array([[74, 85, 45, 58, 88],
       [44, 98, 78, 43, 58],
       [66, 60, 56, 53, 70],
       [66, 58, 46, 79, 60],
       [46, 61, 62, 88, 82],
       [59, 62, 46, 96, 70],
       [66, 80, 63, 76, 73],
       [95, 62, 76, 41, 86],
       [56, 98, 99, 45, 46],
       [42, 98, 67, 86, 81]])
复制代码

但是这样的数据形式很难看到存储的是什么的样的数据,可读性比较差!!

问题:如何让数据更有意义的显示?

# 使用Pandas中的数据结构
score_df = pd.DataFrame(score)
score_df

结果:

给分数数据增加行列索引,显示效果更佳,效果:

 增加行、列索引

# 构造行索引序列
subjects =["语文","数学","英语","政治","体育"]
# 构造列索引序列
stu =['同学'+str(i) for i in range(score_df.shape[0])]
#添加行索引
data = pd.DataFrame(score,columns=subjects, index=stu)
data

结果:

DataFrame的属性

(1)、shape

data.shape

结果:(10, 5)

(2)、index

DataFrame的行索引列表

data.index

结果:

Index(['同学0', '同学1', '同学2', '同学3', '同学4', '同学5', '同学6', '同学7', '同学8', '同学9'], dtype='object')

(3)、columns

DataFrame的列索引列表

data.columns

结果:

Index(['语文', '数学', '英语', '政治', '体育'], dtype='object')

(4)、values

直接获取其中array的值

data.values

结果:

复制代码
array([[74, 85, 45, 58, 88],
       [44, 98, 78, 43, 58],
       [66, 60, 56, 53, 70],
       [66, 58, 46, 79, 60],
       [46, 61, 62, 88, 82],
       [59, 62, 46, 96, 70],
       [66, 80, 63, 76, 73],
       [95, 62, 76, 41, 86],
       [56, 98, 99, 45, 46],
       [42, 98, 67, 86, 81]])
复制代码

(5)、T

转置

data.T

结果:

(6)、head(5):显示前5行内容

如果不补充参数,默认5行。填入参数N则显示前N行

data.head(5)

结果:

(7)、tail(5):显示后5行内容

如果不补充参数,默认5行。填入参数N则显示后N行

data.tail(5)

结果:

 DatatFrame索引的设置

需求:

(1)、修改行列索引值

stu=["学生_"+str(i) for i in range(score_df.shape[0])]
# 必须整体全部修改
data.index= stu
data

结果:

注意:以下修改方式是错误的

#错误修改方式
data.index[3]='学生_3'

报错如下:

(2)、重设索引

reset_index(drop=False)

。设置新的下标索引
。 drop:默认为False,不删除原来索引,如果为True,删除原来的索引值

#重置索引,drop=False
data.reset_index()

结果:

#重置索引,drop=True
data.reset_index(drop=True)

结果:

(3)、 以某列值设置为新的索引

set_index(keys, drop=True)

 • keys:列索引名成或者列索引名称的列表

 • drop:boolean,default True.当做新的索引,删除原来的列

设置新索引案例

创建

df = pd.DataFrame({'month':[1,4,7,10],
                   'year':[2012,2014,2013,2014],
                   'sale':[55,40,84,31]})
df

结果:

 以月份设置新的索引

df.set_index('month')

结果:

设置多个索引,以年和月份

df = pd.DataFrame({'month':[1,4,7,10],
                   'year':[2012,2014,2013,2014],
                   'sale':[55,40,84,31]})
df = df.set_index(['year','month'])
df

结果:

 注:通过刚才的设置,这样DataFrame就变成了一个具有Multiindex的DataFrame。

3、Multilndex与Panel

Multilndex

Multilndex是三维的数据结构:

多级索引(也称层次化索引)是pandas的重要功能,可以在Series、DataFrame对象上拥有2个以及2个以上的索引。

multilndex的特性

打印刚才的df的行索引结果

df = pd.DataFrame({'month':[1,4,7,10],
                   'year':[2012,2014,2013,2014],
                   'sale':[55,40,84,31]})
df = df.set_index(['year','month'])
df

结果:

df.index

结果:

MultiIndex([(2012,  1),
            (2014,  4),
            (2013,  7),
            (2014, 10)],
           names=['year', 'month'])

多级或分层索引对象。

index属性
  names:levels的名称
  levels:每个level的元组值

df.index.names

结果:

FrozenList(['year', 'month'])

levels

df.index.levels

结果:

FrozenList([[2012, 2013, 2014], [1, 4, 7, 10]])

multilndex的创建

arrays = [[1,1,2,2],['red','blue','red','blue']]
pd.MultiIndex.from_arrays(arrays,names=("num","col"))

结果:

MultiIndex([(1,  'red'),
            (1, 'blue'),
            (2,  'red'),
            (2, 'blue')],
           names=['num', 'col'])

三、基本数据操作

 目标

  记忆DataFrame的形状、行列索引名称获取等基本属性
  应用Series和DataFrame的索引进行切片获取
  应用sort_index和sort_values实现索引和值的排序

 为了更好的理解这些基本操作,我们将读取一个真实的股票数据。关于文件操作,后面在介绍,这里只先用一下API

import pandas as pd
# 读取文件
data = pd.read_csv("./data/stock_day.csv")

 结果:

# 删除一些列,让数据更简单些,再去做后面的操作
data = data.drop(["ma5","ma10","ma20","v_ma5","v_ma10","v_ma20"],axis=1)
data

设置axis=1表示按列删除

结果:

1、索引操作

Numpy当中我们已经讲过使用索引选取序列和切片选择,pandas也支持类似的操作,也可以直接使用列名、行名称,甚至组合使用。

(1)、直接使用行列索引(先列后行)

获取'2018-02-27'这天的'close'的结果

# 直接使用行列索引名字的方式(先列后行)
data['open']['2018-02-27']

结果:23.53

# 不支持的操作
#错误 不支持先行后列
data['2018-02-27']['open']
# 错误 不支持下标索引拿数据
data[:1,:2]

(2)、 结合loc或者iloc使用索弓

 获取从'2018-02-27':2018-02-22','open'的结果

# 使用loc:只能指定行列索引的名字
data.loc['2018-02-27':'2018-02-22','open']

结果:

2018-02-27    23.53
2018-02-26    22.80
2018-02-23    22.88
2018-02-22    22.25
Name: open, dtype: float64

使用iloc

data.iloc[:3,:5]

结果:

data.loc['2018-02-27':'2018-02-22','open':'close']

结果:

data.loc[data.index[0:5],['open','close']]

结果:

data.iloc[0:5,data.columns.get_indexer(["open","close"])]

结果:

2、赋值操作

 对DataFrame当中的close列进行重新赋值为1

# 直接修改原来的值
data['close']=1
data

结果:

# 或者
data['close']=2

3、排序

排序有两种形式,一种对于索引进行排序,一种对于内容进行排序

DataFrame排序

(1)、使用df.sort_values(by=,ascending=)

单个键或者多个键进行排序,

参数:

 • by:指定排序参考的键
 • ascending:默认升序
  ascending=False:降序
  ascending=True:升序

#按照开盘价大小进行排序,使用ascending指定按照大小排序
data.sort_values(by="open",ascending=True).head()

结果:

按照多个键进行排序,先根据第一个键排序,如果第一个键相等,则根据第二个键进行排序

# 按照多个键进行排序
data.sort_values(by=['open','high'])

结果:

(2)、使用df.sort index给索引进行排序

这个股票的日期索引原来是从大到小,现在重新排序,从小到大

# 对索引进行排序
data.sort_index()

结果:

Series排序

(1)、使用series.sort_values(ascending=True)进行排序

series排序时,只有一列,不需要参数

data['p_change'].sort_values(ascending=True).head()

结果:

2015-09-01   -10.03
2015-09-14   -10.02
2016-01-11   -10.02
2015-07-15   -10.02
2015-08-26   -10.01
Name: p_change, dtype: float64

(2)、使用series.sort_index0)进行排序

与df一致

# 对索引进行排序
data['p_change'].sort_index().head()

结果:

2015-03-02    2.62
2015-03-03    1.44
2015-03-04    1.57
2015-03-05    2.02
2015-03-06    8.51
Name: p_change, dtype: float64

四、DataFrame运算

算术运算

(1)、add(other)

比如进行数学运算加上具体的一个数字

data['open'].add(1)

结果:

复制代码
2018-02-27    24.53
2018-02-26    23.80
2018-02-23    23.88
2018-02-22    23.25
2018-02-14    22.49
              ...  
2015-03-06    14.17
2015-03-05    13.88
2015-03-04    13.80
2015-03-03    13.52
2015-03-02    13.25
Name: open, Length: 643, dtype: float64
复制代码

(2)、sub(other)

逻辑运算

逻辑运算符号

例如筛选data["open"]>23的日期数据

data["open"]>23

结果:

复制代码
2018-02-27     True
2018-02-26    False
2018-02-23    False
2018-02-22    False
2018-02-14    False
              ...  
2015-03-06    False
2015-03-05    False
2015-03-04    False
2015-03-03    False
2015-03-02    False
Name: open, Length: 643, dtype: bool
复制代码

逻辑判断的结果可以作为筛选的依据

data[data["open"]>23].head()

结果:

完成多个逻辑判断

data[(data["open"]>23)&(data["open"]< 24)].head()

结果:

逻辑运算函数

(1)、query(expr),其中expr:查询字符串

通过query使得刚才的过程更加方便简单

data.query("open<24 & open>23").head()

结果:

另外一种写法:

data[(data["open"]>23)&(data["open"]<24)].head()

 (2)、isin(values)

例如判断'open'是否为23.53和23.85

#可以指定值进行一个判断,从而进行筛选操作
data[data["open"].isin([23.53,23.85])]

结果:

统计运算

describe

综合分析:能够直接得出很多统计结果,count,mean,std,min,max等

# 计算平均值、标准差、最大值、最小值
data.describe()

结果:

统计函数

Numpy当中已经详细介绍,在这里我们演示min(最小值),max(最大值),mean(平均值),median(中位数),var(方差),std(标准差),mode(众数)结果:

mode众数:出现最多的数。idxmax:最大值的索引,idxmin最小值的索引

对于单个函数去进行统计的时候,坐标轴还是按照默认列“columns”(axis=0,default),如果要对行“index”需要指定(axis=1)

(1)、max()、min()

#使用统计函数:0代表列求结果,1 代表行求统计结果
data.max(0)

结果:

复制代码
open                34.99
high                36.35
close                2.00
low                 34.01
volume          501915.41
price_change         3.03
p_change            10.03
turnover            12.56
dtype: float64
复制代码

(2)、std()、var()

方差

data.var(0)

结果:

复制代码
open            1.545255e+01
high            1.662665e+01
close           0.000000e+00
low             1.437902e+01
volume          5.458124e+09
price_change    8.072595e-01
p_change        1.664394e+01
turnover        4.323800e+00
dtype: float64
复制代码

标准差

data.std(0)

结果:

复制代码
open                3.930973
high                4.077578
close               0.000000
low                 3.791968
volume          73879.119354
price_change        0.898476
p_change            4.079698
turnover            2.079375
dtype: float64
复制代码

(3)、median():中位数

中位数为将数据从小到大排列,在最中间的那个数为中位数。如果没有中间数,取中间两个数的平均值

df = pd.DataFrame({'COL1':[2,3,4,5,4,2],
'COL2':[0,1,2,3,4,2]})
df.median()

结果:

COL1    3.5
COL2    2.0
dtype: float64

(4)、idxmax()、idxmin()

求出最大值的位置

data.idxmax(axis=0)

结果:

复制代码
open            2015-06-15
high            2015-06-10
close           2018-02-27
low             2015-06-12
volume          2017-10-26
price_change    2015-06-09
p_change        2015-08-28
turnover        2017-10-26
dtype: object
复制代码

求出最小值的位置

data.idxmin(axis=0)

结果:

复制代码
open            2015-03-02
high            2015-03-02
close           2018-02-27
low             2015-03-02
volume          2016-07-06
price_change    2015-06-15
p_change        2015-09-01
turnover        2016-07-06
dtype: object
复制代码

累计统计函数

那么这些累计统计函数怎么用?下面我们对p_change这一列来求累计统计函数

以上这些函数可以对series和dataframe操作

这里我们按照时间的从前往后来进行累计

(1)、排序

# 排序之后,进行累计求和
data = data.sort_index()
data

结果:

(2)、对p_change进行求和

stock_rise = data['p_change']
# plot方法集成了前面直方图、条形图、饼图、折线图
stock_rise.cumsum()

结果:

复制代码
2015-03-02      2.62
2015-03-03      4.06
2015-03-04      5.63
2015-03-05      7.65
2015-03-06     16.16
               ...  
2018-02-14    112.59
2018-02-22    114.23
2018-02-23    116.65
2018-02-26    119.67
2018-02-27    122.35
Name: p_change, Length: 643, dtype: float64
复制代码

那么如何让这个连续求和的结果更好的显示呢? 

 

如果要使用plot函数,需要导入matplotlib.

import matplotlib.pyplot as plt
# plot显示图形
stock_rise.cumsum().plot()
# 需要调用show,才能显示出结果
plt.show()

结果:

自定义运算

apply(func, axis=0)

  func:自定义函数
  axis=0:默认是列,axis=1为行进行运算

定义一个对列,最大值-最小值的函数

data[['open','close']].apply(lambda x:x.max()- x.min(),axis=0)

结果:

open     22.74
close    22.85
dtype: float64

五、pandas画图

1、pandas.DataFrame.plot

DataFrame.plot (kind='line')

kind:str,需要绘制图形的种类

  'line’ : line plot (default) 默认为折线图
  bar’: vertical bar plot 竖向条形图
  'barh’:horizontal bar plot 水平条形图

  'hist’: histogram 直方图
  'pie’: pie plot 饼图
   'scatter’:scatter plot 散点图

2、pandas.Series.plot

 

 

六、文件读取与存储

我们的数据大部分存在于文件当中,所以pandas会支持复杂的IO操作,pandas的API支持众多的文件格式如CSV、SQL、XLS、JSON、HDF5.

注:最常用的HDF5和CSV文件

1、CSV

(1)、read csv

pandas.read_csv(filepath_or_buffer, sep =',')

  filepath_or_buffer:文件路径
  usecols:指定读取的列名,列表形式

举例:读取之前的股票的数据

# 读取文件,并且指定只获取'open''close'指标
data = pd.read_csv("./data/stock_day.csv", usecols=['open', 'close'])
data

结果:

(2)、 to_csv

 DataFrame.to_csv(path_or_buf=None, sep=',’, columns=None, header=True, index=True, mode='w',encoding=None)

  path_or_buf :文件路径
  sep :分隔符,默认用","隔开
  columns :选择需要的列索引
  header :boolean or list of string,default True,是否写进列索引值
  index:是否写进行索引
  mode:'w':重写,'a'追加

举例:保存读取出来的股票数据

保存'open'列的数据,然后读取查看结果

# 选取10行数据保存,便于观察数据
data[:10].to_csv("./data/test.csv",columns=['open'])

此时data目录下多一个test.csv文件

读取,查看结果

pd.read_csv("./data/test.csv")

结果:

会发现将索引存入到文件当中,变成单独的一列数据。如果需要删除,可以指定index参数,删除原来的文件,重新保存一次。

# index:存储不会讲索引值变成一列数据
data[:10].to_csv("./data/test.csv", columns=['open'], index=False)

读取,查看结果

pd.read_csv("./data/test.csv")

结果:

2、HDF5

read_hdf与to_hdf

HDF5文件的读取和存储需要指定一个键,值为要存储的DataFrame

pandas.read_hdf(path_or_buf, key =None,**kwargs)

从h5文件当中读取数据

  path_or_buffer:文件路径
  key:读取的键
  return:Theselected object

DataFrame.to_hdf(path_or_buf, key,*\kwargs*)

案例:

day_eps_ttm = pd.read_hdf("./data/day_close.h5")
day_eps_ttm

结果:

复制代码
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
File D:\install\anaconda3\envs\DL_Pytorch\Lib\site-packages\pandas\compat\_optional.py:135, in import_optional_dependency(name, extra, errors, min_version)
    134 try:
--> 135     module = importlib.import_module(name)
    136 except ImportError:

File D:\install\anaconda3\envs\DL_Pytorch\Lib\importlib\__init__.py:126, in import_module(name, package)
    125         level += 1
--> 126 return _bootstrap._gcd_import(name[level:], package, level)

File <frozen importlib._bootstrap>:1204, in _gcd_import(name, package, level)

File <frozen importlib._bootstrap>:1176, in _find_and_load(name, import_)

File <frozen importlib._bootstrap>:1140, in _find_and_load_unlocked(name, import_)

ModuleNotFoundError: No module named 'tables'

During handling of the above exception, another exception occurred:

ImportError                               Traceback (most recent call last)
Cell In[11], line 1
----> 1 day_eps_ttm = pd.read_hdf("./data/day_close.h5")
      2 day_eps_ttm

File D:\install\anaconda3\envs\DL_Pytorch\Lib\site-packages\pandas\io\pytables.py:426, in read_hdf(path_or_buf, key, mode, errors, where, start, stop, columns, iterator, chunksize, **kwargs)
    423 if not exists:
    424     raise FileNotFoundError(f"File {path_or_buf} does not exist")
--> 426 store = HDFStore(path_or_buf, mode=mode, errors=errors, **kwargs)
    427 # can't auto open/close if we are using an iterator
    428 # so delegate to the iterator
    429 auto_close = True

File D:\install\anaconda3\envs\DL_Pytorch\Lib\site-packages\pandas\io\pytables.py:566, in HDFStore.__init__(self, path, mode, complevel, complib, fletcher32, **kwargs)
    563 if "format" in kwargs:
    564     raise ValueError("format is not a defined argument for HDFStore")
--> 566 tables = import_optional_dependency("tables")
    568 if complib is not None and complib not in tables.filters.all_complibs:
    569     raise ValueError(
    570         f"complib only supports {tables.filters.all_complibs} compression."
    571     )

File D:\install\anaconda3\envs\DL_Pytorch\Lib\site-packages\pandas\compat\_optional.py:138, in import_optional_dependency(name, extra, errors, min_version)
    136 except ImportError:
    137     if errors == "raise":
--> 138         raise ImportError(msg)
    139     return None
    141 # Handle submodules: if we have submodule, grab parent module from sys.modules

ImportError: Missing optional dependency 'pytables'.  Use pip or conda to install pytables.
View Code
复制代码

需要安装安装tables模块避免不能读取HDF5文件

pip install tables

安装后再次执行,结果如下

存储文件

day_eps_ttm.to_hdf("./data/test.h5", key="day_eps_ttm" )

此时data目录中新增了test.h5文件

再次读取的时候,需要指定键的名字

new_eps = pd.read_hdf("./data/test.h5", key="day_eps_ttm")
new_eps

结果:

注意:pandas优先选择使用HDF5文件存储

  HDF5在存储的时候支持压缩,使用的方式是blosc,这个是速度最快的也是pandas默认支持的
  使用压缩可以提磁盘利用率,节省空间
  HDF5还是跨平台的,可以轻松迁移到hadoop上面

3、JSON

JSON是我们常用的一种数据交换格式,前面在前后端的交互经常用到,也会在存储的时候选择这种格式。所以我们需要知道Pandas如何进行读取和存储JSON格式。
(1)、read_json

pandas.read_json(path_or_buf=None, orient=None, typ='frame', lines=False)

将JSON格式准换成默认的Pandas DataFrame格式
orient :string,indication of expected JSON string format.

lines :boolean, default False

  按照每行读取ison对象

typ:default'frame’,指定转换成的对象类型series或者dataframe

read_josn 案例

这里使用一个新闻标题讽刺数据集,格式为json。is_sarcastic:1讽刺的,否则为0; headline:新闻报道的标题; article_link:链接到原始新闻文章。存储格式为:

读取

orient指定存储的ison格式,lines指定按照行去变成一个样本

json_read = pd.read_json("./data/Sarcasm_Headlines_Dataset.json", orient="records", lines=True)
json_read

结果:

(2)、to_json

DataFrame.to_json(path_or_buf=None, orient=None, lines=False)

  将Pandas 对象存储为ison格式
  path_or_buf=None:文件地址
  orient:存储的json形式,{'split’,'records','index’,'columns','values’)
  lines:一个对象存储为一行

存储文件

json_read.to_json("./data/test.json",orient='records')

修改lines参数为True

json_read.to_json("./data/test.json", orient='records', lines=True)

七、高级处理-缺失值处理

 

1、如何处理NaN

获取缺失值的标记方式(NaN或者其他标记方式)

如果缺失值的标记方式是NaN

判断数据中是否包含NaN:

  pd.isnull(df),

  pd.notnull(df)

存在缺失值nan:

  1、删除存在缺失值的:dropna(axis='rows')

  注:不会修改原数据,需要接受返回值

   2、替换缺失值:fillna(value,inplace=True)

    value:替换成的值
    inplace:True:会修改原数据,False:不替换修改原数据,生成新的对象

如果缺失值没有使用NaN标记,比如使用"?",先替换'?’为np.nan,然后继续处理

案例:电影数据的缺失值处理

 电影数据文件获取

import pandas as pd
# 读取电影数据
movie = pd.read_csv("./data/IMDB-Movie-Data.csv")
movie

结果:

判断缺失值是否存在

pd.notnull(movie)

如果不是缺失值则为True,否则就是False

结果:

通过np.all()判断对象是否都为true,如果返回true则没有缺失值,如果返回false则有缺失值。

import numpy as np
np.all(pd.notnull(movie))

结果:False

pd.isnull()

pd.isnull(movie)

结果:

import numpy as np
np.any(pd.isnull(movie))

结果:True

存在缺失值nan,并且是np.nan

(1)、删除

pandas删除缺失值,使用dropna的前提是,缺失值的类型必须是np.nan

先查看:

movie

结果:

# 不修改原数据
movie.dropna()

结果:

检查是否还有NaN,可以定义新的变量接受或者用原来的变量名

# 可以定义新的变量接受或者用原来的变量名
data = movie.dropna()
np.any(pd.isnull(data))

结果:False

替换缺失值

movie.fillna({ 'Revenue (Millions)': movie['Revenue (Millions)'].mean() }, inplace=True) 

上面只替换了一列,现在替换所有缺失值:

for i in movie.columns:
    if np.all(pd.notnull(movie[i]))== False:
        print(i)
        movie.fillna({ movie[i]: movie[i].mean() }, inplace=True) 

检查

np.any(pd.isnull(movie))

结果:False

不是缺失值nan,有默认标记的

数据是这样的:

读取数据:

wis = pd.read_csv("https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data")
wis

结果:

1、先替换'?’为np.nan

df.replace(to replace=,value=)

  to replace:替换前的值
  value:替换后的值

#把一些其它值标记的缺失值,替换成np.nan
wis =wis.replace(to_replace='?',value=np.nan)
wis

检查是否有nan

np.any(pd.isnull(wis))

结果:True

八、高级处理-数据离散化

为什么要离散化?

连续属性离散化的目的是为了简化数据结构,数据离散化技术可以用来减少给定连续属性值的个数。离散化方法经常作为数据挖掘的工具

什么是数据的离散化?

连续属性的离散化就是在连续属性的值域上,将值域划分为若干个离散的区间,最后用不同的符号或整数 值代表落在每个子区间中的属性值。

离散化有很多种方法,这使用一种最简单的方式去操作

  原始人的身高数据:165,174,160,180,159,163,192,184。

  假设按照身高分几个区间段:150~165,165~180,180~195

这样我们将数据分到了三个区间段,我可以对应的标记为矮、中、高三个类别,最终要处理成一个“哑变量“矩阵

股票的涨跌幅离散化

我们对股票每日的"p_change"进行离散化

读取股票的数据

先读取股票的数据,筛选出p_change数据

data = pd.read_csv("./data/stock_day.csv")
p_change= data['p_change']
p_change

结果:

复制代码
2018-02-27    2.68
2018-02-26    3.02
2018-02-23    2.42
2018-02-22    1.64
2018-02-14    2.05
              ... 
2015-03-06    8.51
2015-03-05    2.02
2015-03-04    1.57
2015-03-03    1.44
2015-03-02    2.62
Name: p_change, Length: 643, dtype: float64
复制代码

将股票涨跌幅数据进行分组

pd.qcut(data, q):

对数据进行分组将数据分组,一般会与value_counts搭配使用,统计每组的个数

series.value_counts0):统计分组次数

# 自行分组
qcut =pd.qcut(p_change,10)
qcut

结果:

复制代码
p_change
(-10.030999999999999, -4.836]    65
(-0.462, 0.26]                   65
(0.26, 0.94]                     65
(5.27, 10.03]                    65
(-4.836, -2.444]                 64
(-2.444, -1.352]                 64
(-1.352, -0.462]                 64
(1.738, 2.938]                   64
(2.938, 5.27]                    64
(0.94, 1.738]                    63
Name: count, dtype: int64
复制代码

计算分到每个组数据个数

复制代码
p_change
(-10.030999999999999, -4.836]    65
(-0.462, 0.26]                   65
(0.26, 0.94]                     65
(5.27, 10.03]                    65
(-4.836, -2.444]                 64
(-2.444, -1.352]                 64
(-1.352, -0.462]                 64
(1.738, 2.938]                   64
(2.938, 5.27]                    64
(0.94, 1.738]                    63
Name: count, dtype: int64
复制代码

自定义区间分组:

pd.cut(data, bins)

# 自己指定分组区间
bins=[-100,-7,-5,-3,0,3,5,7,100]
p_counts=pd.cut(p_change, bins)
p_counts

结果:

复制代码
2018-02-27      (0, 3]
2018-02-26      (3, 5]
2018-02-23      (0, 3]
2018-02-22      (0, 3]
2018-02-14      (0, 3]
                ...   
2015-03-06    (7, 100]
2015-03-05      (0, 3]
2015-03-04      (0, 3]
2015-03-03      (0, 3]
2015-03-02      (0, 3]
Name: p_change, Length: 643, dtype: category
Categories (8, interval[int64, right]): [(-100, -7] < (-7, -5] < (-5, -3] < (-3, 0] < (0, 3] < (3, 5] < (5, 7] < (7, 100]]
复制代码

查看每个区间的个数:

p_counts.value_counts()

结果:

复制代码
p_change
(0, 3]        215
(-3, 0]       188
(3, 5]         57
(-5, -3]       51
(5, 7]         35
(7, 100]       35
(-100, -7]     34
(-7, -5]       28
Name: count, dtype: int64
复制代码

股票涨跌幅分组数据变成one-hot编码

什么是one-hot编码?

把每个类别生成一个布尔列,这些列中只有一列可以为这个样本取值为1.其又被称为热编码,

把下图中左边的表格转化为使用右边形式进行表示:

pandas.get_dummies(data, prefix=None)

  data:array-like,Series, or DataFrame。
  prefix:分组名字

# 得出one-hot编码矩阵
dummies = pd.get_dummies(p_counts, prefix="rise")
dummies

结果:

九、高级处理-合并

如果你的数据由多张表组成,那么有时候需要将不同的内容合并在一起分析

1、pd.concat实现数据合并

pd.concat([data1,data2],axis=1)

按照行或列进行合并,axis=0为列索引,axis=1为行索引

比如我们将刚才处理好的one-hot编码与原数据合并

# 按照行素引进行
pd.concat([data,dummies],axis=1)

结果:

2、pd.merge

pd.merge(left, right, how='inner',on=None)

可以指定按照两组数据的共同键值对合并或者左右各自。
left :DataFrame。
right:另一个DataFrame。
on:指定的共同键
how:按照什么方式连接

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']})
# 默认内连接 innner
pd.merge(left, right, on=["key1", "key2"])
复制代码

结果:

左连接

pd.merge(left, right,how='left', on=["key1", "key2"])

结果:

右连接

pd.merge(left, right,how='right', on=["key1", "key2"])

结果:

外连接:所有数据都连起来,没有的用nan代替

pd.merge(left, right,how='outer', on=["key1", "key2"])

结果:

十、高级处理-交叉表与透视表

目标
  应用crosstab和pivot table实现交叉表与透视表

1、交叉表与透视表什么作用

探究股票的涨跌与星期几有关?

以下图当中表示,week代表星期几,1,0代表这一天股票的涨跌幅是好还是坏,里面的数据代表比例可以理解为所有时间为星期一等等的数据当中涨跌幅好坏的比例

即星期一跌的有0.504,涨的是0.496

交叉表:交叉表用于计算一列数据对于另外一列数据的分组个数(用于统计分组频率的特殊透视表)

pd.crosstab(value1.value2)

透视表:透视表是将原有的DataFrame的列分别作为行索引和列索引,然后对指定的列应用聚集函数

data.pivot_table()

DataFrame.pivot_table([], index=[])

准备两列数据,星期数据以及涨跌幅是好是坏数据

进行交叉表计算

data.index

结果:

Index(['2018-02-27', '2018-02-26', '2018-02-23', '2018-02-22', '2018-02-14',
       '2018-02-13', '2018-02-12', '2018-02-09', '2018-02-08', '2018-02-07',
       ...
       '2015-03-13', '2015-03-12', '2015-03-11', '2015-03-10', '2015-03-09',
       '2015-03-06', '2015-03-05', '2015-03-04', '2015-03-03', '2015-03-02'],
      dtype='object', length=643)

将日期转换成weekday,即转化为0,1,2,3,4

date = pd.to_datetime(data.index).weekday
date

结果:

date = pd.to_datetime(data.index).weekday
date

结果:

Index([1, 0, 4, 3, 2, 1, 0, 4, 3, 2,
       ...
       4, 3, 2, 1, 0, 4, 3, 2, 1, 0],
      dtype='int32', length=643)

给data添加一个week列

data['week']= date

假如把p_change按照大小去分个类,0为界限,大于0为1,小于0为0,然后给data添加一个posi_neg列

data['posi_neg']=np.where(data['p_change']>0,1,0)

结果如下:

# 通过交叉表找寻两列数据的关系
count =pd.crosstab(data['week'],data['posi_neg'])
count

结果

即pd.crosstab求出来的是数量。

以上步骤的代码如下:

# 寻找星期几跟股票张得的关系
#1、先把对应的日期找到星期几
date = pd.to_datetime(data.index).weekday
data['week']= date
#2、假如把p_change按照大小去分个类0为界限
data['posi_neg']=np.where(data['p_change']>0,1,0)
# 通过交叉表找寻两列数据的关系
count =pd.crosstab(data['week'],data['posi_neg'])

但是我们看到count只是每个星期日子的好坏天数,并没有得到比例,该怎么去做?

 对于每个星期一等的总天数求和,运用除法运算求出比例

求和

# 算数运算,先求和
sum = count.sum(axis=1).astype(np.float32)
sum

结果:

week
0    125.0
1    131.0
2    132.0
3    128.0
4    127.0
dtype: float32

进行相除操作,得出比例

pro =count.div(sum,axis=0)
pro

结果:

 查看效果

使用plot画出这个比例,使用stacked的柱状图

pro.plot(kind='bar')
plt.show()

结果:

pro.plot(kind='bar',stacked=True)
plt.show()

结果:

 使用pivot table(透视表)实现

使用透视表,刚才的过程更加简单

复制代码
import pandas as pd
import numpy as np
# 读取文件
data = pd.read_csv("./data/stock_day.csv")
data['posi_neg']=np.where(data['p_change']>0,1,0)
date = pd.to_datetime(data.index).weekday
data['week']= date
# 通过透视表,将整个过程变成更简单一些
data.pivot_table(['posi_neg'], index='week')
复制代码

结果:

知道其中一个百分比,另一个百分比不需要了。

由上可知pivot_table求出的是比例。

十一、高级处理-分组与聚合

分组与聚合通常是分析数据的一种方式,通常与一些统计函数一起使用,查看数据的分组情况

想一想其实刚才的交叉表与透视表也有分组的功能,所以算是分组的一种形式,只不过他们主要是计算次数或者计算比例!!看其中的效果:

什么是分组与聚合?

 分组API

DataFrame.groupby(key,as_index=False)

key:分组的列数据,可以多个

案例:不同颜色的不同笔的价格数据

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

结果:

进行分组,对颜色分组,price进行聚合

# 分组,求平均值
col.groupby(['color'])['price1'].mean()

结果:

color
green    2.025
red      2.380
white    5.560
Name: price1, dtype: float64

另一种表达方式:

col['price1'].groupby(col['color']).mean()

分组,数据的结构不变

col.groupby(['color'],as_index=False)['price1'].mean()

结果:

 



感谢您的阅读,如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮。本文欢迎各位转载,但是转载文章之后必须在文章页面中给出作者和原文连接
posted on   周文豪  阅读(20)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
历史上的今天:
2022-02-07 Volatile详解
2022-02-07 多线程之锁优化
2022-02-07 内存可见性以及synchronized实现可见性和Volatile实现可见性
2022-02-07 JVM内存结构、Java对象模型和Java内存模型
2022-02-07 多线程之线程优先级
2022-02-07 多线程之线程停止
2021-02-07 Mysql训练:第二高的薪水(IFNULL,OFFSET,LIMIT)
点击右上角即可分享
微信分享提示