程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长

+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

python数据分析利器——pandas(一)

发布于2019-08-22 16:57     阅读(749)     评论(0)     点赞(24)     收藏(1)


数据分析是python的一大应用领域。pandas基于numpy实现,常与numpy和matplotlib一同使用,关于numpy可以查阅我以前的博文——进阶python数据分析,python科学计算包numpy。
Pandas 有很多高级的功能,但是想要掌握高级功能前,需要先掌握它的基础知识,Pandas 中的数据结构算是非常基础的知识之一了。

Pandas 常用的数据结构有两种:Series 和 DataFrame。这些数据结构构建在 Numpy 数组之上,这意味着它们效率很高。我们来分别看看这些数据结构都长什么样子吧。

import pandas as pd
pd.Series()
pd.DataFrame()
  • 1
  • 2
  • 3

和学习 numpy 一样,学习 pandas 还是遵循的 Python 中「万物皆对象」的原则,既然把数据表当对象,我们就按着数据表的创建、数据表的存载、数据表的获取、数据表的合并和连接、数据表的重塑和透视、和数据表的分组和整合来学习 Pandas,
本篇博文目录如下:

数据表的创建

Series创建

Dataframe创建

创建Panel

数据表的存储

数据表的索引与切片

at iat

loc iloc

多层索引

那么首先我们来看看如何创建数据表

数据表的创建

数据表有三大类型

Series: 一维数据,类似于 python 中的基本数据的 list 或 NumPy 中的 1D array。Pandas 里最基本的数据结构

DataFrame: 二维数据,类似于 R 中的 data.frame 或 Matlab 中的 Tables。DataFrame 是 Series 的容器,最常见的数据类型是二维的 DataFrame,其中每行代表一个示例 (instance),每列代表一个特征 (feature)。DataFrame 可理解成是 Series 的容器,每一列都是一个 Series,或者 Series 是只有一列的 DataFrame。

Panel:三维数据。Panel 可理解成是 DataFrame 的容器。

Series创建

创建 Series 只需用下面一行代码

pd.Series( x, index=idx )
  • 1

其中 x 可以是

列表 (list)
numpy 数组 (ndarray)
字典 (dict)

用列表创建

s = pd.Series([10.2,13.65,17.70, 18])
s
  • 1
  • 2

在这里插入图片描述在创建 Series 时,如果不显性设定 index,那么 Python 给定一个默认从 0 到 N-1 的值,其中 N 是 x 的长度。

Series s 也是一个对象,用 dir(s) 可看出关于 Series 所有的属性和内置函数,其中最重要的是

用 s.values 打印 s 中的元素

在这里插入图片描述
用 s.index 打印 s 中的元素对应的索引
在这里插入图片描述
以上创建的 Series 和 numpy 数组比多了「索引」,但这种 0,1,2,3 的索引是在没有什么描述意义。那么用2019 年 4 月 1 日到 2019 年 4 月 4 日日期来当索引

dates = pd.date_range('20190401',periods=4)
s2 = pd.Series( [10.2,13.65,17.70, 18], index=dates )
s2
  • 1
  • 2
  • 3

在这里插入图片描述
显然,s2 比 s 包含的信息更多,这是 s2 的索引是一组日期对象,数据类型是 datetime64,频率是 D (天)。
在这里插入图片描述
你甚至还可以给 s2 命名,比如叫午餐费
在这里插入图片描述

用numpy数组创建

除了用列表,我们还可以用 numpy 数组来生成 Series。在下例中,我们加入缺失值 np.nan,并分析一下 Series 中另外 5 个属性或内置函数的用法:

len: s 里的元素个数
shape: s 的形状 (用元组表示)
count: s 里不含 nan 的元素个数
unique: 返回 s 里不重复的元素
value_counts: 统计 s 里非 nan 元素的出现次数

对照上面函数的用法,下面的输出一看就懂了吧。
在这里插入图片描述

用字典

创建 Series 还可以用字典。字典的「键值对」的「键」自动变成了 Series 的索引 (index),而「值」自动变成了Series 的值 (values)。代码如下 (下列用 name 参数来对 s3 命名)

data_dict = { '阿里巴巴': 187.07, '拼多多': 21.83, '京东': 30.79, '百度': 184.77 }
s3 = pd.Series(data_dict, name='中概股')
s3.index.name = '股票名称'
s3
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述
Series 是 Pandas 里面最基本的数据结构,但是对应每个索引只有一个元素 ,因此 Series 处理不了每个索引对应多个元素 。而 DataFrame 可以解决这个问题。

Dataframe的创建

创建 DataFrame 只需用下面一行代码

pd.DataFrame( x, index=idx,columns=col )
  • 1

x 是位置参数
index 是默认参数,默认值为 idx = range(0, x.shape[0])
columns 是默认参数,默认值为 col = range(0, x.shape[1])
其中 x 可以是

二维列表 (list)
二维 numpy 数组 (ndarray)
字典 (dict),其值是一维列表、numpy 数组或 Series
另外一个 DataFrame

用列表和二维numpy数组创建

df1 = pd.DataFrame( [[1, 2, 3], [4, 5, 6]] )
df1 = pd.DataFrame( np.array([[1, 2, 3], [4, 5, 6]]) )
df1
  • 1
  • 2
  • 3

在这里插入图片描述从上面的运行结果可以看出:
index = 0 到 r-1,r 是 x 的行数
colmns = 0 到 c-1,c 是 x 的列数

用字典创建

company = ['阿里巴巴', '京东', '华为', '平安', '工商银行', '沃尔玛']
data = {'行业': ['电商', '电商', '科技', '金融', '金融', '零售'],
        '价格': [176.92, 25.95, 172.97, 41.79, 196.00, 99.55],
        '交易量': [16175610, 27113291, 18913154, 10132145, 2626634, 8086946],
        '雇员': [101550, 175336, 100000, 60348, 36600, 2200000]}
df2 = pd.DataFrame( data, index=company)
df2.name='美股'
df2.index.name = '代号'
df2
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

在这里插入图片描述字典的「键值对」的「键」自动变成了 DataFrame 的栏 (columns),而「值」自动变成了 DataFrame 的值 (values),而其索引 (index) 需要另外定义。我们来分别看一下df2的值(values),列(column)和索引(index)
在这里插入图片描述

查看Dataframe

我们可以从头或从尾部查看 DataFrame 的 n 行,分别用 df2.head(n) 和 df2.tail(n),如果没有设定 n,默认值为 5 行。

在这里插入图片描述

统计Dataframe

我们用 df2.describe() 还可以看看 DataFrame 每栏的统计描述信息。函数 describe() 只对「数值型变量」有用 (没有对「字符型变量」行业栏做统计),统计量分别包括出现次数、平均值、标准差、最小值,25-50-75 百分数值,最大值。一般做数据分析第一步会用这个表大概看看:
数据是否有缺失值 (每个栏下的 count 是否相等)?
数据是否有异常值 (最小值 min 和最大值 max 是否太极端)?
在这里插入图片描述

升维Dataframe

我们用 MultiIndex.from_tuples() 还可以赋予 DataFrame 多层索引 (实际上增加了维度,多层索引的 DataFrame 实际上是三维数据)。

df2.index = pd.MultiIndex.from_tuples( 
            [('其他公司','阿里巴巴'), ('其他公司','京东'), 
             ('其他公司','华为'), ('金融公司','平安'), 
             ('金融公司','工商银行'), ('美国公司','沃尔玛')] )
df2
  • 1
  • 2
  • 3
  • 4
  • 5

在这里插入图片描述

三维Panel的创建

创建 Panel 只需用下面一行代码

pd.Panel( x, item=itm, major_axis=n1,minor_axis=n2 )
  • 1

其中 x 可以是
三维列表 (list)
三维 numpy 数组 (ndarray)
字典 (dict),其值是 DataFrame

用三维数组ndarray创建

import pandas as pd
import numpy as np
pn = pd.Panel(np.random.randn(3, 5, 4))
pn
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述

用字典创建

dates = pd.date_range('20190401',periods=4)
price = {'去年价格': [27.2, 27.65, 27.70, 28],
        '今年价格': [27.1, 27.55, 27.45, 28.1]}
df1 = pd.DataFrame( price, index=dates )
price = {'今年价格': [367, 369.8, 378.2, 380.6],
        '去年 价格': [369.5, 370.1, 380, 382.1]}
df2 = pd.DataFrame(price, index=dates )
p_data = {'午餐' : df1, '衣服' : df2}
pn = pd.Panel(p_data)
pn
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

在这里插入图片描述既然panel是dataframe的容器,让我们来查看两个 DataFrame 的内容
在这里插入图片描述
现实中做量化分析时,数据量都会很大,一般都是从量化平台中或者下载好的 csv 中直接读取。本节介绍如何从量化平台「万矿」中读取数据来创建「多维数据表」的。首先在 https://www.windquant.com 注册一个账号,点击「研究」后在点开一个 Notebook 作为你的研究环境.

数据表的存储

本节介绍数据表的「保存」和「加载」,以 excel 和 csv 格式举例。
保存只是为了下次再用处理好的 DataFrame
加载可以不用重新再定义 DataFrame
DataFrame 可以被保存为 Excel, csv, SQL 和 HDF5 格式,其语句一看就懂,用 to_数据格式,具体如下:
to_excel()
to_csv()
to_sql()
to_hdf()
如果要加载某种格式的数据到 DataFrame 里,用 read_数据格式,具体如下:
read_excel()
read_csv()
read_sql()
read_hdf()

Excel格式

df = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6]]))
df.to_excel(r'C:\Users\xiaoLiu\Desktop\Python\lizi.xlsx', sheet_name='Sheet1')
  • 1
  • 2

我们发现对应文件夹路径下多了一个文件
在这里插入图片描述打开后发现就是我们写入的数据表
在这里插入图片描述pd.read_excel( ‘文件路径名’,‘表名’ ) 即可加载该文件并存成 DataFrame 形式
在这里插入图片描述

csv格式

用 pd.to_csv 函数将 DataFrame 保存为 .csv 格式,注意如果 index 没有特意设定,最后不要把 index 值存到 csv 文件中。具体写法:pd.to_csv( ‘文件路径名’,index=False )

import pandas as pd
data = {'行业': ['电商', '电商', '科技', '金融', '金融', '零售'],
        '价格': [176.92, 25.95, 172.97, 41.79, 196.00, 99.55],
        '交易量': [16175610, 27113291, 18913154, 10132145, 2626634, 8086946],
        '雇员': [101550, 175336, 100000, 60348, 36600, 2200000]}
df=pd.DataFrame(data)
df.to_csv(r'C:\Users\xiaoLiu\Desktop\Python\lizi1.csv', index=False,encoding='utf_8_sig')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

运行结果如下:
在这里插入图片描述
在这里插入图片描述用 pd.read_csv( ‘文件路径名’ ) 即可加载该文件并存成 DataFrame 形式
在这里插入图片描述df2 里面第一栏是 df 的 index,由于没有具体的 columns 名称,系统给它一个 “Unamed: 0”。因此在存储 df 的时候,如果 df.index 没有特意设定,记住要在 to_csv() 中把 index 设置为 False。

数据表的索引和切片

DataFrame 的索引或切片可以基于标签 (label-based) ,也可以基于位置 (position-based),不像 numpy 数组的索引或切片只基于位置。
DataFrame 的索引或切片有四大类:
索引单元素:
基于标签的 at
基于位置的 iat

切片 columns:
用 . 来切片单列
用 [] 来切片单列或多列
基于标签的 loc
基于位置的 iloc

切片 index:
用 [] 来切片单行或多行
基于标签的 loc
基于位置的 iloc

切片 index 和 columns:
基于标签的 loc
基于位置的 iloc
总体规律,基于标签就用 at 和 loc,基于位置就用 iat 和 iloc。下面我们来一类类分析:

索引单个元素

两种方法来索引单个元素,情况 1 基于标签 at,情况 2 基于位置 iat。

情况 1 - df.at[‘idx_i’, ‘attr_j’]
情况 2 - df.iat[i, j]

Python 里的中括号 [] 会代表很多意思,比如单元素索引,多元素切片,布尔索引等等,因此让 Python 猜你用的 [] 意图会很低效。如果你想索引单元素,明明白白的用 at 和 iat 效率最高。

company = ['阿里巴巴', '京东', '华为', '平安', '工商银行', '沃尔玛']
data = {'行业': ['电商', '电商', '科技', '金融', '金融', '零售'],
        '价格': [176.92, 25.95, 172.97, 41.79, 196.00, 99.55],
        '交易量': [16175610, 27113291, 18913154, 10132145, 2626634, 8086946],
        '雇员': [101550, 175336, 100000, 60348, 36600, 2200000]}
df = pd.DataFrame( data, index=company)
df.at["华为","价格"]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在这里插入图片描述
另一种方法

df.iloc[2,1] #用 iat 获取第 3 行第 2 列对应的元素。
  • 1

在这里插入图片描述

切片

切片 columns
切片单个 columns:切片单个 columns 会返回一个 Series,有以下四种情况。情况 1 用点 .;情况 2 用中括号 [];情况 3 基于标签 loc,情况 4 基于位置 iloc。

情况 1 - df.attr_i
情况 2 - df[‘attr_i’]
情况 3 - df.loc[:, ‘attr_i’]
情况 4 - df.iloc[:, i]

情况 1和情况 2 非常简单,如下图:
在这里插入图片描述

情况 3 和 4 的 loc 和 iloc 可类比于上面的 at 和 iat。带 i 的基于位置 (位置用整数表示,i 也泛指整数),不带 i 的基于标签。里面的冒号 : 代表所有的 index (和 numpy 数组里的冒号意思相同)。

个人建议,如果追求简洁和方便,用 . 和 [];如果追求一致和清晰,用 loc 和 iloc。
运行示意如下:在这里插入图片描述

切片多个 columns

切片多个 columns 会返回一个 原 DataFrame 的子集,有以下三种情况。情况 1 用中括号 [];情况 2 基于标签 loc,情况 3 基于位置 iloc。
情况 1 - df[[‘attr_i’, ‘attr_j’]]
情况 2 - df.loc[:, ‘attr_i’:‘attr_j’]
情况 3 - df.iloc[:, i:j]

和切片单个 columns 相比:

情况 1 用一个列表来储存一组属性 ‘attr_i’, ‘attr_j’,然后在放进中括号 [] 里获取它们,实例如下:

df[['价格','雇员']]
  • 1

在这里插入图片描述
情况 2 用 ‘attr_i’:‘attr_j’ 来获取从属性 i 到属性 j 的 sub-DataFrame
情况 3 用 i:j 来获取从列 i+1 到列 j 的 sub-DataFrame
在这里插入图片描述

建议:如果追求简洁和方便,用 [];如果追求一致和清晰,用 loc 和 iloc。

切片单个 index

切片单个 index 有时会返回一个 Series,有以下两种情况。情况 1 基于标签 loc,情况 2 基于位置 iloc。

情况 1 - df.loc[‘idx_i’, :]
情况 2 - df.iloc[i, :]
情况 3 - df[i:i+1]
情况 4 - df[‘idx_i’:‘idx_i’]

情况 1 和 2 的 loc 和 iloc 可类比于上面的 at 和 iat。带 i 的基于位置 (位置用整数表示,i 也泛指整数),不带 i 的基于标签。里面的冒号 : 代表所有的 columns (和 numpy 数组里的冒号意思相同)。情况 3 用中括号 [] 加「位置」,位置 i:i+1 有前闭后开的性质。如果要获取第 i+1 行,需要用 i:i+1。情况 4 用中括号 [] 加「标签」,标签没有前闭后开的性质。如果要获取标签 i,只需要用 ‘idx_i’:‘idx_i’。为什么不能只用 ‘idx_i’ 呢?原因是 Python 会把 df[‘idx_i’] 当成切片 columns,然后发现属性中没有 ‘idx_i’ 这一个字符,会报错的。

建议:只用 loc 和 iloc。情况 3 太麻烦,获取一行还要用 i:i+1。情况 4 的 df[‘idx_i’] 很容易和切片 columns 中的语句 df[‘attr_j’] 混淆。
下面我们来看看如何使用这四种情况来切片单个index
在这里插入图片描述

切片多个 index

切片多个 index 会返回一个 sub-DataFrame(原DataFrame的子集),有以下四种情况。情况 1 用中括号 [] 加「位置」,情况 2 用中括号 [] 加「标签」,情况 3 基于标签 loc,情况 4 基于位置 iloc。
情况 1 - df[i:j]
情况 2 - df[‘idx_i’:‘idx_j’]
情况 3 - df.loc[‘idx_i’:‘idx_j’, :]
情况 4 - df.iloc[i:j, :]

和切片单个 index 相比:
情况 1 用 [i:j] 来获取行 i+1 到行 j 的 sub-DataFrame
情况 2 用 [‘idx_i’:‘idx_j’] 来获取标签 i 到标签 j 的 sub-DataFrame
情况 3 用 loc 加 ‘idx_i’:‘idx_j’ 来获取从标签 i 到标签 j 的 sub-DataFrame
情况 4 用 iloc 加 i:j 来获取从行 i+1 到行 j 的 sub-DataFrame

个人建议,只用 loc 和 iloc。情况 1 和 2 的 df[] 很容易混淆中括号 [] 里的到底是切片 index 还是 columns。下面我们来看看这四种情况如何使用:
在这里插入图片描述

切片 index 和 columns

切片多个 index 和 columns 会返回一个 sub-DataFrame,有以下两种情况。情况 1 基于标签 loc,情况 2 基于位置 iloc。

情况 1 - df.loc[‘idx_i’:‘idx_j’, ‘attr_k’:‘attr_l’]
情况 2 - df.iloc[i:j, k:l]

清清楚楚,明明白白,用 loc 和 iloc。
接着我们来看看效果
在这里插入图片描述

高级索引

高级索引 (advanced indexing) 可以用布尔索引 (boolean indexing) 和调用函数 (callable function) 来实现,两种方法都返回一组“正确”的索引,而且可以和 loc , iloc , [] 一起套用,具体形式有以下常见几种:
df.loc[布尔索引, :]
df.iloc[布尔索引, :]
df[布尔索引]
df.loc[调用函数, :]
df.iloc[调用函数, :]
df[调用函数]

还有以下罕见几种:
df.loc[:, 布尔索引]
df.iloc[:, 布尔索引]
df.loc[:, 调用函数]
df.iloc[:, 调用函数]
当我们要过滤掉雇员小于 100,000 人的公司,我们可以用 loc 加上布尔索引。

print( df.雇员 >= 100000 )
df.loc[ df.雇员 >= 100000, : ]
  • 1
  • 2

在这里插入图片描述
当我们要找出交易量大于平均交易量的所有公司,我们可以用 loc 加上匿名函数 (这里 x 代表 df)。

df.loc[lambda x:x.交易量>x.交易量.mean(),:]
  • 1

在这里插入图片描述
在上面基础上再加一个条件 – 价格要在 100 之上 (这里 x 还是代表 df)

df.loc[ lambda x: (x.交易量 > x.交易量.mean())  & (x.价格 > 100), : ]
  • 1

在这里插入图片描述

多层索引 DataFrame

Series 只有 index,上面刚介绍完多层 index,DataFrame 有 index 和 columns,它们可以设置成多层吗?下面代码用 MultiIndex 函数创建「多层 index 」midx 和「多层columns」mcol。
midx 和 mcol 都是对象,各种都有 levels, labels, names 等性质。

import pandas as pd
data = [ ['电商', 101550, 176.92, 16175610], 
         ['电商', 175336, 25.95, 27113291], 
         ['金融', 60348, 41.79, 10132145], 
         ['金融', 36600, 196.00, 2626634] ]
midx = pd.MultiIndex( 
          levels=[['中国','美国'],
                  ['BABA', 'JD', 'GS', 'MS']], 
          labels=[[0,0,1,1],[0,1,2,3]],
          names=['地区', '代号'])
mcol = pd.MultiIndex( 
          levels=[['公司数据','交易数据'],
                  ['行业','雇员','价格','交易量']], 
          labels=[[0,0,1,1],[0,1,2,3]],
          names=['概括','细分'])
df = pd.DataFrame(data, index=midx, columns=mcol)
df
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

在这里插入图片描述
在第一层 index 的 ‘中国’ 做切片,得到一个含两层 columns 的 DataFrame。

df.loc['中国'].loc['BABA':'JD']
  • 1

在这里插入图片描述

调位 level

如果你不喜欢 index level 的顺序,可用 swaplevel 将它们调位。

df.swaplevel('地区', '代号')
  • 1

在这里插入图片描述

重设index

data = {'地区': ['中国', '中国', '美国', '美国'],
        '代号': ['BABA', 'JD', 'MS', 'GS'],
        '行业': ['电商', '电商', '金融', '金融'],
        '价格': [176.92, 25.95, 41.79, 196.00],
        '交易量': [16175610, 27113291, 10132145, 2626634],
        '雇员': [101550, 175336, 60348, 36600] }
df = pd.DataFrame( data )
df
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在这里插入图片描述

总结

【创建数据表】

创建 Series, DataFrame, Panel 用下面语句
pd.Series(x, index=idx)
其中 x 可以是:
列表 (list)
numpy 数组 (ndarray)
字典 (dict)

pd.DataFrame(x, index=idx, columns=col)
其中 x 可以是:
二维列表 (list)
二维 numpy 数组 (ndarray)
字典 (dict),其值是一维列表、numpy 数组或 Series
另外一个 DataFrame

pd.Panel(x, item=itm, major_axis=n1, minor_axis=n2)
其中 x 可以是:
三维列表 (list)
三维 numpy 数组 (ndarray)
字典 (dict),其值是 DataFrame

【索引和切片数据表】

在索引或切片 DataFrame,有很多种方法。最好记的而不易出错的是用基于位置的 at 和 loc,和基于标签的 iat 和 iloc,具体来说,索引用 at 和 iat,切片用 loc 和 iloc。带 i 的基于位置,不带 i 的基于标签。
用 MultiIndex 可以创建多层索引的对象,获取 DataFrame df 的信息可用

df.loc[1st].loc[2nd]
df.loc[1st].iloc[2nd]
df.iloc[1st].loc[2nd]
df.iloc[1st].iloc[2nd]

要调换 level 可用

df.index.swaplevel(0,1)
df.columns.swaplevel(0,1)

要设置和重设 index 可用

df.set_index( columns )
df.reset_index()



所属网站分类: 技术文章 > 博客

作者:38373

链接:https://www.pythonheidong.com/blog/article/53100/b656c3acfe1f4b737c3b/

来源:python黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

24 0
收藏该文
已收藏

评论内容:(最多支持255个字符)