Pandas使用方法

Pandas使用方法

1 Pandas介绍

在这里插入图片描述

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

2 DataFrame基本操作

2.1 DataFrame结构

DataFrame是的一个二维数组,既有行索引,又有列索引,有数据

  • 行索引,表明不同行,横向索引,叫index,0轴,axis=0
  • 列索引,表名不同列,纵向索引,叫columns,1轴,axis=1
  • 数据(即行列中对应的数据)

在这里插入图片描述

2.2 DatatFrame的属性及方法

  • df.shape
    • 获取DF的行数和列数
  • df.index
    • 获取DataFrame的行索引列表
  • df.columns
    • 获取DataFrame的列索引列表
  • df.values
    • 直接获取其中array的值
  • df.T
    • 将DataFrame转置
  • df.ndim
    • 获取数据的维度
  • df.dtypes
    • 获取数据的类型
  • df.head()
    • 显示前5行内容
  • df.tail()
    • 显示后5行内容
  • df.info
    • 显示df的概览

2.3 创建DataFrame

# 方法1:以传入字典形式创建DataFrame
df = pd.DataFrame({'name':['james','curry','iversion'],
                       'age':['18','20','19'],
                       'national':['us','china','us']})

# 方法2:指定内容、index、column形式创建DataFrame
df = pd.DataFrame([['snow','M',22],['tyrion','M',32],['sansa','F',18],['arya','F',14]], index=list('abcd'), columns=['name','gender','age'])

# 方法3:from_dict方法生成DataFrame
data = {'Name':['zs','ls','we'],'Age':['10','20','30'],'country':['中国','日本','韩国']}
df = pd.DataFrame.from_dict(data)

2.4 DataFrame添加数据

2.4.1 DataFrame添加一列数据
# 添加score列
df['score'] = [57,74,87]
2.4.2 DataFrame插入一列数据
# 1.将数据框的列名全部提取出来存放在列表里 
col_name=df1.columns.tolist()
# 2.在列索引为2的位置插入一列,列名为:city,刚插 入时不会有值,整列都是NaN
col_name.insert(2,'city')
# 3.DataFrame.reindex() 对原行/列索引重新构建 索引值
df1=df1.reindex(columns=col_name)
# 4.给city列赋值
df1['city']=['北京','山西','湖北','澳门']
2.4.3 DataFrame插入一行数据
# 直接给某行赋值
df1.iloc[1] = [11,22,33]
2.4.4 在DataFrame最后添加一行数据
new=pd.DataFrame({'name':'lisa', 'gender':'F', 'age':19 },index=[0])
df1=df1.append(new,ignore_index=True)  # ignore_index=False,表示不按原来的索引,从0开始自 动递增

2.5 DataFrame删除数据

df = pd.DataFrame(np.arange(9).reshape(3,3),columns=['one','two','three'])
# 删除one整列数据
df1=df.drop(['one'],axis=1, inplace=True)
# 删除索引标签为0,1的两行数据
df2=df.drop([0,1],axis=0, inplace=False)  # 注意:此处的[0,1]是行索引标签名而非行索引下标

2.6 DatatFrame索引的设置

2.6.1 修改行列索引值
stock_code = ["股票_" + str(i) for i in range(stock_day_rise.shape[0])]

# 这种方式必须整体全部修改
df.index = stock_code

注意:以下修改方式是错误的(不能只修改其中的某个索引的值)

# 错误修改方式
df.index[3] = '股票_3'
2.6.2 修改某个索引值
# 把行标签bj改为beijing
df.rename(index={'bj':'beijing'}, inplace=True)

# 把列标签a改为aaa
df.rename(index={'a':'aaa'}, inplace=True)  
2.6.3 重设索引
  • pd.reset_index(drop=False)
    • 设置新的下标索引
    • drop:默认为False,不删除原来索引,如果为True,删除原来的索引值
# 重置索引,drop=False
data.reset_index()

    index    2017-01-02   2017-01-03   2017-01-04   2017-01-05   2017-01-06
0    股票_0    -0.065440    -1.309315    -1.454515    0.579730    1.486024
1    股票_1    -1.732167    -0.834137    0.458615    -0.803918    -0.468786
2    股票_2    0.218056    0.199014    0.713468    0.548426    0.386234
3    股票_3    -0.422079    -0.337024    0.423285    -1.230792    1.328438
4    股票_4    -1.725307    0.075918    -1.917084    -0.165358    1.076451
5    股票_5    -0.815768    -0.286753    1.204420    0.733660    -0.062145
6    股票_6    -0.988209    -1.018152    -0.954173    -0.815390    0.502682
7    股票_7    -0.100341    0.611962    -0.068503    0.747384    0.143011
8    股票_8    1.000262    0.342420    -2.252971    0.939211    1.140803
9    股票_9    2.520647    1.553848    1.722530    0.612701    0.608881
# 重置索引,drop=True
data.reset_index(drop=True)

    2017-01-02    2017-01-03   2017-01-04   2017-01-05   2017-01-06
0    -0.065440    -1.309315    -1.454515    0.579730    1.486024
1    -1.732167    -0.834137    0.458615    -0.803918    -0.468786
2    0.218056    0.199014    0.713468    0.548426    0.386234
3    -0.422079    -0.337024    0.423285    -1.230792    1.328438
4    -1.725307    0.075918    -1.917084    -0.165358    1.076451
5    -0.815768    -0.286753    1.204420    0.733660    -0.062145
6    -0.988209    -1.018152    -0.954173    -0.815390    0.502682
7    -0.100341    0.611962    -0.068503    0.747384    0.143011
8    1.000262    0.342420    -2.252971    0.939211    1.140803
9    2.520647    1.553848    1.722530    0.612701    0.608881
2.6.4 以某列值设置为新的行索引
  • set_index(keys, drop=True)
    • keys : 列索引名成或者列索引名称的列表
    • drop : boolean, default True.当做新的索引,删除原来的列,设置为False将保留原来的列
  • df.index.name
    • 行索引上面的名字
  month  sale  year
0  1      55    2012
1  4      40    2014
2  7      84    2013
3  10     31    2014
# 把'month'列设置为索引
df.set_index('month')
'''
       sale  year
month
1      55    2012
4      40    2014
7      84    2013
10     31    2014
'''
2.6.5 以某行的值设置为新的列索引
res = df.set_axis(df.iloc[0], axis=1, inplace=False)
res.columns.name=None  # 设置列索引的名称为空

2.7 索引操作

在这里插入图片描述

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

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

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

# 不支持的操作
# 错误
data['2018-02-27']['open']
# 错误
data[:1, :2]
2.7.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
Name: open, dtype: float64

# 使用iloc可以通过索引的下标去获取
# 获取前100天数据的'open'列的结果
data.iloc[0:100, 0:2].head()

            open    high    close    low
2018-02-27    23.53    25.88    24.16    23.53
2018-02-26    22.80    23.78    23.53    22.80
2018-02-23    22.88    23.37    22.82    22.71

2.8 赋值操作

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

# 直接修改原来的值
data['close'] = 1  # 推荐使用
# 或者
data.close = 1

2.9 排序

排序有两种形式:

  • 一种对于索引进行排序
  • 一种对于内容进行排序
2.9.1 df.sort_values()

df.sort_values(by=, ascending=)

  • 单个键或者多个键进行排序,默认升序
  • by: 要排序的列的名称,多列则需要用[]括起来
  • ascending=False: 降序
  • ascending=True: 升序
# 按照涨跌幅大小进行排序 , 使用ascending指定按照大小排序
data = data.sort_values(by='p_change', ascending=False).head()

              open     high     close    low      volume price_change p_change turnover
2015-08-28    15.40    16.46    16.46    15.00    117827.60    1.50    10.03    4.03
2015-05-21    27.50    28.22    28.22    26.50    121190.11    2.57    10.02    4.15
2016-12-22    18.50    20.42    20.42    18.45    150470.83    1.86    10.02    3.77
2015-08-04    16.20    17.35    17.35    15.80    94292.63    1.58    10.02    3.23
2016-07-07    18.66    18.66    18.66    18.41    48756.55    1.70    10.02    1.67

# 按照多个键进行排序
data = data.sort_values(by=['open', 'high'])
              open    high     close     low      volume price_change p_change turnover
2015-06-15    34.99    34.99    31.69    31.69    199369.53    -3.52    -10.00    6.82
2015-06-12    34.69    35.98    35.21    34.01    159825.88    0.82    2.38    5.47
2015-06-10    34.10    36.35    33.85    32.23    269033.12    0.51    1.53    9.21
2017-11-01    33.85    34.34    33.83    33.10    232325.30    -0.61    -1.77    5.81
2015-06-11    33.17    34.98    34.39    32.51    173075.73    0.54    1.59    5.92
2.9.2 df.sort_index()

df.sort_index()(by=, ascending=)

使用索引进行排序

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

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

              open    high    close    low    volume    price_change p_change turnover
2015-03-02    12.25   12.67   12.52    12.20   96291.73    0.32      2.62      3.30
2015-03-03    12.52   13.06   12.70    12.52   139071.61   0.18      1.44      4.76
2015-03-04    12.80   12.92   12.90    12.61   67075.44    0.20      1.57      2.30
2015-03-05    12.88   13.45   13.16    12.87   93180.39    0.26      2.02      3.19
2015-03-06    13.17   14.48   14.28    13.13   179831.72   1.12      8.51      6.16

3 DataFrame运算

3.1 算术运算
  • add(other)

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

data['open'].add(1)  # open列里的每个元素+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
  • sub(other)

如果想要得到每天的涨跌大小?求出每天 close- open价格差

# 1、筛选两列数据
close = data['close']
open1 = data['open']
# 2、收盘价减去开盘价
data['m_price_change'] = close.sub(open1)
data.head()

           open   high   close    low   price_change  p_change  turnover my_price_change
2018-02-27 23.53  25.88   24.16   23.53    0.63       2.68      2.39     0.63
2018-02-26 22.80  23.78   23.53   22.80    0.69       3.02      1.53     0.73
2018-02-23 22.88  23.37   22.82   22.71    0.54       2.42      1.32     -0.06
2018-02-22 22.25  22.76   22.28   22.02    0.36       1.64      0.90     0.03
2018-02-14 21.49  21.99   21.92   21.48    0.44       2.05      0.58     0.43
3.2 逻辑运算
3.2.1 逻辑运算符<、 >、|、 &
  • 例如筛选p_change > 2的日期数据
    • data[‘p_change’] > 2 返回bool值的列表
data['p_change'] > 2

2018-02-27     True
2018-02-26     True
2018-02-23     True
2018-02-22    False
2018-02-14     True
# 逻辑判断的结果可以作为筛选的依据
data[data['p_change'] > 2]    # 返回data['p_change'] > 2为True的所有数据

             pen    high   close  low    price_change p_change  turnover  my_price_change
2018-02-27   23.53  25.88  24.16  23.53  0.63         2.68      2.39      0.63
2018-02-26   22.80  23.78  23.53  22.80  0.69         3.02      1.53      0.73
2018-02-23   22.88  23.37  22.82  22.71  0.54         2.42      1.32      -0.06
2018-02-14   21.49  21.99  21.92  21.48  0.44         2.05      0.58      0.43
2018-02-12   20.70  21.40  21.19  20.63  0.82         4.03      0.81      0.49
  • 完成一个多个逻辑判断, 筛选p_change > 2并且open > 15
data[(data['p_change'] > 2) & (data['open'] > 15)]

              open   high   close  low   price_change  p_change  turnover my_price_change
2017-11-14    28.00  29.89  29.34  27.68   1.10         3.90      6.10     1.34
2017-10-31    32.62  35.22  34.44  32.20   2.38         7.42      9.05     1.82
2017-10-27    31.45  33.20  33.11  31.45   0.70         2.16      8.35     1.66
2017-10-26    29.30  32.70  32.41  28.92   2.68         9.01      12.56    3.11
3.3 逻辑运算函数

df.query(expr)

  • expr:查询字符串

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

data.query("p_change > 2 & turnover > 15")

df.isin(values)

判断’turnover’列中的值是否有4.19, 2.39

# 可以指定值进行一个判断,从而进行筛选操作
data[data['turnover'].isin([4.19, 2.39])]

            open  high  close  low   price_change  p_change  turnover  my_price_change
2018-02-27  23.53 25.88 24.16  23.53  0.63         2.68      2.39      0.63
2017-07-25  23.07 24.20 23.70  22.64  0.67         2.91      4.19      0.63
2016-09-28  19.88 20.98 20.86  19.71  0.98         4.93      2.39      0.98
2015-04-07  16.54 17.98 17.54  16.50  0.88         5.28      4.19      1.00
3.4 统计运算
3.4.1 describe()

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

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

在这里插入图片描述

3.4.2 统计函数

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

函数名作用
sum累加和
mean平均值
median中位数
min最小值
max最大值
mode众数–出现次数最多的数
abs绝对值
prod累乘
std标准差
var方差
idxmax最大值的位置下标
idxmin最小值的位置下标

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

3.5 累计统计函数
函数作用
cumsum计算前1/2/3/…/n个数的和
cummax计算前1/2/3/…/n个数的最大值
cummin计算前1/2/3/…/n个数的最小值
cumprod计算前1/2/3/…/n个数的积
3.6 自定义运算
  • apply(func, axis=0)
    • func:自定义函数
    • axis=0:默认是列,axis=1为行进行运算
  • 定义一个对列,最大值-最小值的函数
  • pd.apply(lambda x: x.max() - x.min(), axis=0)
    • lambda x x为接收的一个参数
    • x.max() - x.min() 返回运算结果
data[['open', 'close']].apply(lambda x: x.max() - x.min(), axis=0)

open     22.74
close    22.85
dtype: float64

4 Series基本操作

  • Series是一个一维数组
  • Series结构只有行索引

在这里插入图片描述

3.1 创建series

通过已有数据创建

  • 指定内容,默认索引
pd.Series(np.arange(10))
  • 指定索引
pd.Series([6.7,5.6,3,10,2], index=[1,2,3,4,5])

通过字典数据创建

pd.Series({'red':100, ''blue':200, 'green': 500, 'yellow':1000})

3.2 series获取属性和值

  • index

    • 获取行索引,返回一个列表
  • values

    • 获取Series值,返回一个列表

3.3 series运算

两个Series间运算

两个Series间的运算是按照相同的index进行加减乘除,没有相同的index则为NAN

在这里插入图片描述

3.4 Series.to_list()

把Series内容转换成列表

3.5 排序

3.5.1 sort_values()
  • 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
3.5.2 sort_index()

与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

5 Pandas画图

5.1 pandas.DataFrame.plot

  • DataFrame.plot(x=None, y=None, kind=‘line’)
    • x : label or position, default None
    • y : label, position or list of label, positions, default None
      • Allows plotting of one column versus another
    • kind : str
      • ‘line’ : line plot (default)
      • ‘bar’ : vertical bar plot
      • ‘barh’ : horizontal bar plot
        • 关于“barh”的解释:
        • http://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.plot.barh.html
      • ‘hist’ : histogram
      • ‘pie’ : pie plot
      • ‘scatter’ : scatter plot

更多参数细节:https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.plot.html?highlight=plot#pandas.DataFrame.plot

5.2 pandas.Series.plot

更多参数细节:https://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.plot.html?highlight=plot#pandas.Series.plot

6 文件读取与存储

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

注:最常用的HDF5和CSV文件

在这里插入图片描述

6.1 CSV

6.1.1 pd.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'])

               open    close
2018-02-27    23.53    24.16
2018-02-26    22.80    23.53
2018-02-23    22.88    22.82
2018-02-22    22.25    22.28
2018-02-14    21.49    21.92
6.1.2 pd.to_csv()
  • DataFrame.to_csv(path_or_buf=None, sep=’, ’, columns=None, header=True, index=True, mode=‘w’, encoding=None)
    • path_or_buf :string or file handle, default None
    • sep :character, default ‘,’
    • columns :sequence, optional
    • mode:‘w’:重写, ‘a’ 追加
    • index:是否写进行索引
    • header :boolean or list of string, default True,是否写进列索引值

案例:

  • 保存’open’列的数据
# 选取10行数据保存,便于观察数据
data[:10].to_csv("./data/test.csv", columns=['open'])
  • 读取,查看结果
pd.read_csv("./data/test.csv")

     Unnamed: 0    open
0    2018-02-27    23.53
1    2018-02-26    22.80
2    2018-02-23    22.88
3    2018-02-22    22.25
4    2018-02-14    21.49
5    2018-02-13    21.40
6    2018-02-12    20.70
7    2018-02-09    21.20
8    2018-02-08    21.79
9    2018-02-07    22.69

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

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

6.2 HDF5

6.2.1 pd.read_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/stock_data/day/day_eps_ttm.h5")

如果读取的时候出现以下错误

在这里插入图片描述

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

pip install tables

在这里插入图片描述

6.2.2 pd.to_hdf()
  • 存储文件
day_eps_ttm.to_hdf("./data/test.h5", key="day_eps_ttm")

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

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

6.3 JSON

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

6.3.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.

    • ‘split’ : dict like {index -> [index], columns -> [columns], data -> [values]}

      • split 将索引总结到索引,列名到列名,数据到数据。将三部分都分开了
    • ‘records’ : list like [{column -> value}, … , {column -> value}]

      • records 以columns:values的形式输出
    • ‘index’ : dict like {index -> {column -> value}}

      • index 以index:{columns:values}...的形式输出
    • ‘columns’ : dict like {column -> {index -> value}}

      ,默认该格式

      • colums 以columns:{index:values}的形式输出
    • ‘values’ : just the values array

      • values 直接输出值
  • lines : boolean, default False

    • 按照每行读取json对象
  • typ : default ‘frame’, 指定转换成的对象类型series或者dataframe

read_josn 案例

数据介绍

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

{"article_link": "https://www.huffingtonpost.com/entry/versace-black-code_us_5861fbefe4b0de3a08f600d5", "headline": "former versace store clerk sues over secret 'black code' for minority shoppers", "is_sarcastic": 0}
{"article_link": "https://www.huffingtonpost.com/entry/roseanne-revival-review_us_5ab3a497e4b054d118e04365", "headline": "the 'roseanne' revival catches up to our thorny political mood, for better and worse", "is_sarcastic": 0}
  • 读取

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

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

结果为:

在这里插入图片描述

6.3.2 to_json()
  • DataFrame.to_json(

    path_or_buf=None

    ,

    orient=None

    ,

    lines=False

    )

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

案例

  • 存储文件
json_read.to_json("./data/test.json", orient='records')

结果

[{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/versace-black-code_us_5861fbefe4b0de3a08f600d5","headline":"former versace store clerk sues over secret 'black code' for minority shoppers","is_sarcastic":0},{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/roseanne-revival-review_us_5ab3a497e4b054d118e04365","headline":"the 'roseanne' revival catches up to our thorny political mood, for better and worse","is_sarcastic":0},{"article_link":"https:\/\/local.theonion.com\/mom-starting-to-fear-son-s-web-series-closest-thing-she-1819576697","headline":"mom starting to fear son's web series closest thing she will have to grandchild","is_sarcastic":1},{"article_link":"https:\/\/politics.theonion.com\/boehner-just-wants-wife-to-listen-not-come-up-with-alt-1819574302","headline":"boehner just wants wife to listen, not come up with alternative debt-reduction ideas","is_sarcastic":1},{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/jk-rowling-wishes-snape-happy-birthday_us_569117c4e4b0cad15e64fdcb","headline":"j.k. rowling wishes snape happy birthday in the most magical way","is_sarcastic":0},{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/advancing-the-worlds-women_b_6810038.html","headline":"advancing the world's women","is_sarcastic":0},....]
  • 修改lines参数为True
json_read.to_json("./data/test.json", orient='records', lines=True)

结果

{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/versace-black-code_us_5861fbefe4b0de3a08f600d5","headline":"former versace store clerk sues over secret 'black code' for minority shoppers","is_sarcastic":0}
{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/roseanne-revival-review_us_5ab3a497e4b054d118e04365","headline":"the 'roseanne' revival catches up to our thorny political mood, for better and worse","is_sarcastic":0}
{"article_link":"https:\/\/local.theonion.com\/mom-starting-to-fear-son-s-web-series-closest-thing-she-1819576697","headline":"mom starting to fear son's web series closest thing she will have to grandchild","is_sarcastic":1}
{"article_link":"https:\/\/politics.theonion.com\/boehner-just-wants-wife-to-listen-not-come-up-with-alt-1819574302","headline":"boehner just wants wife to listen, not come up with alternative debt-reduction ideas","is_sarcastic":1}
{"article_link":"https:\/\/www.huffingtonpost.com\/entry\/jk-rowling-wishes-snape-happy-birthday_us_569117c4e4b0cad15e64fdcb","headline":"j.k. rowling wishes snape happy birthday in the most magical way","is_sarcastic":0}...

6.4 拓展

优先选择使用HDF5文件存储

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

7 高级-缺失值与重复值处理

7.1 如何处理NAN

  • 判断数据是否为NaN:
    • pd.isnull(df),
    • pd.notnull(df)
  • 处理方式:
    • 存在缺失值NAN,并且是np.NAN:
      • 1、删除存在缺失值的:dropna(axis=‘rows’)
        • 注:不会修改原数据,需要接受返回值
      • 2、替换缺失值:fillna(value, inplace=True)
        • value:替换成的值
        • inplace:True:会修改原数据,False:不替换修改原数据,生成新的对象
    • 不是缺失值NAN,有默认标记的

7.2 电影数据的缺失值处理

  • 电影数据文件获取
# 读取电影数据
movie = pd.read_csv("./data/IMDB-Movie-Data.csv")
7.2.1 判断缺失值是否存在
  • pd.notnull()
pd.notnull(movie)
Rank    Title    Genre    Description    Director    Actors    Year    Runtime (Minutes)    Rating    Votes    Revenue (Millions)    Metascore
0    True    True    True    True    True    True    True    True    True    True    True    True
1    True    True    True    True    True    True    True    True    True    True    True    True
2    True    True    True    True    True    True    True    True    True    True    True    True
3    True    True    True    True    True    True    True    True    True    True    True    True
4    True    True    True    True    True    True    True    True    True    True    True    True
5    True    True    True    True    True    True    True    True    True    True    True    True
6    True    True    True    True    True    True    True    True    True    True    True    True
7    True    True    True    True    True    True    True    True    True    True    False    True
np.all(pd.notnull(movie))  # 获取一行中不包含NAN的数据
7.2.2 处理存在缺失值,并且是np.NAN
  • 1、df.dropna(axis=, how=)删除空值
    • axis=0 删除一行中的数据
    • axis=1 删除一列中的数据
    • how=all 删除一行中全是NAN的行数据
    • how=any 删除一行中包含NAN的行数据

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

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

# 可以定义新的变量接受或者用原来的变量名
data = movie.dropna()
  • 2、df.fillna()填充缺失值
# 使用平均值填充缺失值
movie['Revenue (Millions)'].fillna(movie['Revenue (Millions)'].mean(), inplace=True)

# 使用不同的常数填充缺失值
movie.fillna({0:10,1:20,2:30})  # 0列填充10,1列填充20,2列填充30

# 使用当前列前一个非NAN数据的值填充
movie['Revenue (Millions)'].fillna(method='ffill')

# 使用当前列后一个非NAN数据的值填充
movie['Revenue (Millions)'].fillna(method='bfill')

替换所有缺失值:

for i in movie.columns:
    if np.all(pd.notnull(movie[i])) == False:
        print(i)
        movie[i].fillna(movie[i].mean(), inplace=True)
7.2.3 处理不是NAN,有默认标记的

数据是这样的:

在这里插入图片描述

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

以上数据在读取时,可能会报如下错误:

URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:833)>

解决办法:

# 全局取消证书验证
import ssl
ssl._create_default_https_context = ssl._create_unverified_context

处理思路分析:

  • 1、先替换‘?’为np.nan
    • df.replace(to_replace=, value=)
      • to_replace:替换前的值
      • value:替换后的值
# 把一些其它值标记的缺失值,替换成np.nan
wis = wis.replace(to_replace='?', value=np.nan)
  • 2、在进行缺失值的处理
# 删除
wis = wis.dropna()
7.2.4 处理重复值
  • df.duplicated()
    • 判断每一行是否重复(结果是bool值,TRUE代表重复的)
  • df.drop_duplicates()
    • 去除全部的重复行
  • df.drop_duplicates([‘A’])
    • 去除指定列重复行
  • df.drop_duplicates([‘A’],keep=‘last’)
    • 保留重复行中的最后一行

7.3 小结

  • isnull、notnull判断是否存在缺失值【知道】
  • dropna删除np.nan标记的缺失值【知道】
  • fillna填充缺失值【知道】
  • replace替换具体某些值【知道】

8 高级-数据离散化

8.1 为什么要离散化

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

8.2 什么是数据的离散化

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

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

  • 原始人的身高数据:165,174,160,180,159,163,192,184
  • 假设按照身高分几个区间段:150~165, 165180,180195

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

在这里插入图片描述

8.3 股票的涨跌幅离散化

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

8.3.1 读取股票的数据

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

data = pd.read_csv("./data/stock_day.csv")
p_change= data['p_change']
8.3.2 将股票涨跌幅数据进行分组

在这里插入图片描述

使用的工具:

  • pd.qcut(data, q, labels=[])
    • 特点:把样本平均分到指定数量的类别(q)中
    • 对数据进行分组,将数据分组 一般会与value_counts搭配使用,统计每组的个数
    • q: 要分成多少个组
    • labels: 设置分组名称
  • series.value_counts():统计分组次数
# 自行分组
qcut = pd.qcut(p_change, 10)
# 计算分到每个组数据个数
qcut.value_counts()

自定义区间分组:

  • pd.cut(data, bins)
    • 特点:把区间平均分成指定数量的份数中,再对落在每个区间的样本打上相应的区间标签
    • bins: 指定分组区间
# 自己指定分组区间
bins = [-100, -7, -5, -3, 0, 3, 5, 7, 100]
p_counts = pd.cut(p_change, bins)
8.3.3 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")

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RUDbRcgZ-1604760507795)(images/哑变量矩阵.png)]

8.4 小结

  • 数据离散化【知道】
  • qcut、cut实现数据分组【知道】
  • get_dummies实现哑变量矩阵【知道】

9 高级-合并

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

9.1 pd.concat实现数据合并

  • pd.concat([data1, data2], axis=1, ignore_index=False)
    • 按照行或列进行合并,axis=0为列索引,axis=1为行索引
    • ignore_index 是否按照合并后的索引递增
      • True: 索引由0开始递增
      • False: 跟随索引合并后的索引递增

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

在这里插入图片描述

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

9.2 df.join

  • df.jion专注于行合并,不能合并存在相同列名的DataFrame
9.2.1 how=left

以left的行作为基础,将left和right的列铺开,符合left行index的填充到对应列中,不符合的弃掉,没有值的用NAN填充

df=pd.DataFrame({'Red':[1,3,5],'Green':[5,0,3]},index=list('abc')) 
df2=pd.DataFrame({'Blue':[1,9,8],'Yellow':[6,6,7]},index=list('cde'))
df.join(df2)  # 默认how='left'

在这里插入图片描述

9.2.2 how=‘right’

以right的行作为基础,将left和right的列铺开,符合right行index的填充到对应列中,不符合的弃掉,没有值的用NAN填充

df.join(df2,how='right')

在这里插入图片描述

9.2.3 how=‘outer’

将left和right的行和列铺开,没有值的列用NAN填充

pd.concat([df, df2],sort=False)

在这里插入图片描述

9.3 pd.merge

专注列的合并

  • pd.merge(left, right, how=‘inner’, on=None, left_on=None, right_on=None)
    • 可以指定按照两组数据的共同键值对合并或者左右各自
    • left: A DataFrame object
    • right: Another DataFrame object
    • on: Columns (names) to join on. Must be found in both the left and right DataFrame objects.
    • left_on=None, right_on=None:指定左右键
Merge methodSQL Join NameDescription
leftLEFT OUTER JOINUse keys from left frame only
rightRIGHT OUTER JOINUse keys from right frame only
outerFULL OUTER JOINUse union of keys from both frames
innerINNER JOINUse intersection of keys from both frames
9.3.1 how=inner
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']})

# 默认inner连接
result = pd.merge(left, right, on=['key1', 'key2'])

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

9.4 小结

  • pd.concat([数据1, 数据2], axis=**)【知道】
  • pd.merge(left, right, how=, on=)【知道】
    • how – 以何种方式连接
    • on – 连接的键的依据是哪几个

10 高级-交叉表与透视表

10.1 交叉表与透视表什么作用

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

以下图当中表示,week代表星期几,1,0代表这一天股票的涨跌幅是好还是坏,里面的数据代表比例

可以理解为所有时间为星期一等等的数据当中涨跌幅好坏的比例

在这里插入图片描述

在这里插入图片描述

10.2 使用crosstab(交叉表)实现上图

  • 交叉表:

    交叉表用于计算一列数据对于另外一列数据的分组个数(寻找两个列之间的关系)

    • pd.crosstab(value1, value2)
    • DataFrame.pivot_table([], index=[])

10.3 案例分析

10.3.1 数据准备
  • 准备两列数据,星期数据以及涨跌幅是好是坏数据
  • 进行交叉表计算
# 寻找星期几跟股票张得的关系
# 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)

# 进行相除操作,得出比例
pro = count.div(sum, axis=0)
10.3.2 查看效果

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

pro.plot(kind='bar', stacked=True)
plt.show()
10.3.3 使用pivot_table(透视表)实现

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

# 通过透视表,将整个过程变成更简单一些
data.pivot_table(['posi_neg'], index='week')

10.4 小结

  • 交叉表与透视表的作用【知道】

11 高级-分组与聚合

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

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

在这里插入图片描述

11.1 什么分组与聚合

在这里插入图片描述

11.2 分组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]})

   color    object    price1    price2
0    white    pen    5.56    4.75
1    red    pencil    4.20    4.12
2    green    pencil    1.30    1.60
3    red    ashtray    0.56    0.75
4    green    pen    2.75    3.15
  • 进行分组,对颜色分组,price进行聚合
# 分组,求平均值
col.groupby(['color'])['price1'].mean()
col['price1'].groupby(col['color']).mean()

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

# 分组,数据的结构不变
col.groupby(['color'], as_index=False)['price1'].mean()

color    price1
0    green    2.025
1    red    2.380
2    white    5.560
  • groupby.groups

    • 查看分组
  • groupby.count()

    • 查看分组后的数量
  • 查看分组的情况

gb = col.groupby(['color'])

for name, group in gb:
print(name)  # 组的名字
print(group)  # 组具体内容

gb.get_group('green')  # 获取green分组内容
  • 按照多列进行分组
gb = df11.groupby(['color', 'object'])
for name, group in gb:
    print(group)
    
gb.get_group(('green','pen'))  # 获取green pen分组内容
  • 聚合函数agg()
df1.groupby('key1').agg('sum')

# 可以同时做多个聚合运算
df1.groupby('key1').agg(['sum','mean','std'])

# 自定义函数,传入agg方法中 grouped.agg(func)
def peak_range(df):
  return df.max() - df.min()
df1.groupby('key1').agg(peak_range)

# 同时应用多个聚合函数
df1.groupby('key1').agg(['mean', 'std', 'count', peak_range])

# 给每列作用不同的聚合函数
dict_mapping = {
  'Data1':['mean','max'],
  'Data2':'sum'
}
df1.groupby('key1').agg(dict_mapping)

11.3 星巴克零售店铺数据

现在我们有一组关于全球星巴克店铺的统计数据,如果我想知道美国的星巴克数量和中国的哪个多,或者我想知道中国每个省份星巴克的数量的情况,那么应该怎么办?

数据来源:https://www.kaggle.com/starbucks/store-locations/data

在这里插入图片描述

11.3.1 数据获取

从文件中读取星巴克店铺数据

# 导入星巴克店的数据
starbucks = pd.read_csv("./data/starbucks/directory.csv")
11.3.2 进行分组聚合
# 按照国家分组,求出每个国家的星巴克零售店数量
count = starbucks.groupby(['Country']).count()

画图显示结果

count['Brand'].plot(kind='bar', figsize=(20, 8))
plt.show()

在这里插入图片描述

假设我们加入省市一起进行分组

# 设置多个索引,set_index()
starbucks.groupby(['Country', 'State/Province']).count()

在这里插入图片描述

仔细观察这个结构,与我们前面讲的哪个结构类似??

与前面的MultiIndex结构类似

11.4 小结

  • groupby进行数据的分组【知道】

12 多层索引

12.1 DataFrame创建多层索引

# 方法一:
df = DataFrame(np.random.randint(0,150,size=(6,4)), 
               columns = ['zs','ls','ww','zl'],
               index = [['python','python','math','math','En','En'],['期中','期末','期 中','期末','期中','期					末']])

# 方法二:pd.MultiIndex.from_arrays()
class1=['python','python','math','math','En','En'] 
class2=['期中','期末','期中','期末','期中','期末'] 
m_index2 = pd.MultiIndex.from_arrays([class1,class2]) 
df23 = pd.DataFrame(np.random.randint(0,150,(6,4)),index=m_index2)
                
# 方法三:pd.MultiIndex.from_product()
class1=['python','math','En']
class2=['期中','期末'] 
m_index2=pd.MultiIndex.from_product([class1,class2])
df2=pd.DataFrame(np.random.randint(0,150,(6,4)),index=m_index2)

12.2 多层索引对象的索引操作

# 获取一级索引
df2.loc['python']

# 获取多个一级索引
df2.loc[['math','En']]

# 获取一行
df2.loc['python','期中']

# 获取一个值
df2.loc['python','期中'][0]

13 时间序列

pd.date_range(start, end, periods, freq, closed)

该函数主要用于生成一个固定频率的时间索引,在调用构造方法时,必须指定startendperiods中的两个参数

值,否则报错。

属性作用
start起始日期
end结束日期
periods固定数量,取值为整数或None
freq日期偏移量,取值为string, 默认为’D’, freq=‘1h30min’(间隔1小时30分) freq=‘10D’ (间隔10天)
closed有两个值,left和right;left包含开始时间,不包含结束时间,right与之相反
  • 时间序列频率:

    • D 日历日的每天

      B 工作日的每天

      H 每小时

      T或min 每分钟

      S 每秒

      L或ms 每毫秒

      U 每微秒

      M 日历日的月底日期

      BM 工作日的月底日期

      MS 日历日的月初日期

      BMS 工作日的月初日期

13.1时间序列在dataFrame中的作用

# 可以将时间作为索引
index = pd.date_range(start='20190101',periods=10)
df = pd.Series(np.random.randint(0,10,size = 10),index=index)

# truncate这个函数将before指定日期之前的值全部过滤出去,after指定日期之前的值全部过滤出去.
btime = df.truncate(before='2019-01-8')
print(after)

long_ts =
pd.Series(np.random.randn(1000),index=pd.date_range('1/1/2019',periods=1000))
print(long_ts)

# 根据年份获取
result = long_ts['2020']
print(result)

# 年份和日期获取
result = long_ts['2020-05']
print(result)

# 使用切片
result = long_ts['2020-05-01':'2020-05-06']
print(result)

# 通过between_time()返回位于指定时间段的数据集
index=pd.date_range("2018-03-17","2018-03-30",freq="2H")
ts = pd.Series(np.random.randn(157),index=index)
print(ts.between_time("7:00","17:00"))  # 获取7:00-17:00期间的数据
# 将时间戳转化成时间根式
pd.to_datetime(1554970740000,unit='ms')

# 处理一列
df = pd.DataFrame([1554970740000, 1554970800000, 1554970860000],columns =
['time_stamp'])
pd.to_datetime(df['time_stamp'],unit='ms').dt.tz_localize('UTC').dt.tz_convert('Asia/S
hanghai')#先赋予标准时区,再转换到东八区
                                                                               
# 处理中文
pd.to_datetime('2019年10月10日',format='%Y年%m月%d日')
      |

| freq | 日期偏移量,取值为string, 默认为’D’, freq=‘1h30min’(间隔1小时30分) freq=‘10D’ (间隔10天) |
| closed | 有两个值,left和right;left包含开始时间,不包含结束时间,right与之相反 |

  • 时间序列频率:

    • D 日历日的每天

      B 工作日的每天

      H 每小时

      T或min 每分钟

      S 每秒

      L或ms 每毫秒

      U 每微秒

      M 日历日的月底日期

      BM 工作日的月底日期

      MS 日历日的月初日期

      BMS 工作日的月初日期

13.1时间序列在dataFrame中的作用

# 可以将时间作为索引
index = pd.date_range(start='20190101',periods=10)
df = pd.Series(np.random.randint(0,10,size = 10),index=index)

# truncate这个函数将before指定日期之前的值全部过滤出去,after指定日期之前的值全部过滤出去.
btime = df.truncate(before='2019-01-8')
print(after)

long_ts =
pd.Series(np.random.randn(1000),index=pd.date_range('1/1/2019',periods=1000))
print(long_ts)

# 根据年份获取
result = long_ts['2020']
print(result)

# 年份和日期获取
result = long_ts['2020-05']
print(result)

# 使用切片
result = long_ts['2020-05-01':'2020-05-06']
print(result)

# 通过between_time()返回位于指定时间段的数据集
index=pd.date_range("2018-03-17","2018-03-30",freq="2H")
ts = pd.Series(np.random.randn(157),index=index)
print(ts.between_time("7:00","17:00"))  # 获取7:00-17:00期间的数据
# 将时间戳转化成时间根式
pd.to_datetime(1554970740000,unit='ms')

# 处理一列
df = pd.DataFrame([1554970740000, 1554970800000, 1554970860000],columns =
['time_stamp'])
pd.to_datetime(df['time_stamp'],unit='ms').dt.tz_localize('UTC').dt.tz_convert('Asia/S
hanghai')#先赋予标准时区,再转换到东八区
                                                                               
# 处理中文
pd.to_datetime('2019年10月10日',format='%Y年%m月%d日')
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值