pandas介绍

Python Data Analysis Library

pandas是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。Pandas 纳入 了大量库和一些标准的数据模型,提供了高效地操作大型结构化数据集所需的工具。

pandas核心数据结构

数据结构是计算机存储、组织数据的方式。 通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。数据结构往往同高效的检索算法和索引技术有关。

Series

Series可以理解为一个一维的数组,只是index名称可以自己改动。类似于定长的有序字典,有Index和 value。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import pandas as pd
import numpy as np

# 创建一个空的系列
s = pd.Series()
# 从ndarray创建一个Series
data = np.array(['张三','李四','王五','赵柳'])
s = pd.Series(data)
s = pd.Series(data,index=['100','101','102','103'])
# 从字典创建一个Series
data = {'100' : '张三', '101' : '李四', '102' : '王五'}
s = pd.Series(data)
# 从标量创建一个Series
s = pd.Series(5, index=[0, 1, 2, 3])

访问Series中的数据

1
2
3
4
5
# 使用索引检索元素
s = pd.Series([1,2,3,4,5],index = ['a','b','c','d','e'])
print(s[0], s[:3], s[-3:])
# 使用标签检索数据
print(s['a'], s[['a','c','d']])

Series常用属性:类似numpy

1
2
3
4
5
6
s1.values #  所有的值   返回一个ndarray
s1.index # 所有的索引
s1.dtype
s1.size
s1.ndim
s1.shape

pandas日期类型数据处理

1
2
3
4
5
6
7
8
9
# pandas识别的日期字符串格式
dates = pd.Series(['2011', '2011-02', '2011-03-01', '2011/04/01',
'2011/05/01 01:01:01', '01 Jun 2011',
'20110701','2011/8/1'])
# to_datetime() 转换日期数据类型
dates = pd.to_datetime(dates)
print(dates, dates.dtype, type(dates))
# 获取时间的某个日历字段的数值
print(dates.dt.day)

Series.dt日期相关操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Series.dt.year	# The year of the datetime.  年
Series.dt.month # The month as January=1, December=12. 月
Series.dt.day # The days of the datetime. 日
Series.dt.hour # The hours of the datetime. 时
Series.dt.minute # The minutes of the datetime. 分
Series.dt.second # The seconds of the datetime. 秒
Series.dt.microsecond # The microseconds of the datetime. 微秒
Series.dt.week # The week ordinal of the year. 一年当中的第几周
Series.dt.weekofyear # The week ordinal of the year.一年当中的第几周
Series.dt.dayofweek # The day of the week with Monday=0, Sunday=6. 星期几
Series.dt.weekday # The day of the week with Monday=0, Sunday=6.星期几
Series.dt.dayofyear # The ordinal day of the year. 一年当中的第几天
Series.dt.quarter # The quarter of the date. 季度
Series.dt.is_month_start # Indicates whether the date is the first day of the month.
Series.dt.is_month_end # Indicates whether the date is the last day of the month.
Series.dt.is_quarter_start # Indicator for whether the date is the first day of a quarter.
Series.dt.is_quarter_end # Indicator for whether the date is the last day of a quarter.
Series.dt.is_year_start # Indicate whether the date is the first day of a year.
Series.dt.is_year_end # Indicate whether the date is the last day of the year.
Series.dt.is_leap_year # Boolean indicator if the date belongs to a leap year. 是不是闰年
Series.dt.days_in_month # The number of days in the month. 一个月当中的第几天

日期运算

1
2
3
4
5
# datetime日期运算
delta = dates - pd.to_datetime('1970-01-01')
print(delta, delta.dtype, type(delta)) # ... dtype: timedelta64[ns] timedelta64[ns] ...
# 把时间偏移量换算成天数
print(delta.dt.days) # 在这只能timedelta64.dt.days 不能写其他的

通过指定周期和频率,使用date_range()函数就可以创建日期序列。 默认情况下,频率是’D’。

1
2
3
4
5
6
7
8
9
10
11
12
import pandas as pd
# 以日为频率
datelist = pd.date_range('2019/08/21', periods=5)
print(datelist)
# 以月为频率
datelist = pd.date_range('2019/08/21', periods=5,freq='M')
print(datelist)
# 构建某个区间的时间序列
start = pd.datetime(2017, 11, 1)
end = pd.datetime(2017, 11, 5)
dates = pd.date_range(start, end)
print(dates)

bdate_range()用来表示商业日期范围,不同于date_range(),它不包括星期六和星期天。

1
2
3
4
5
import pandas as pd
datelist = pd.bdate_range('2011/11/03', periods=5)
print(datelist)

freq = 'B'

DataFrame

DataFrame是一个类似于表格(有行有列)的数据类型,可以理解为一个二维数组,索引有两个维度(行级索引,列级索引),可更改。DataFrame具有以下特点:

  • 列和列之间可以是不同的类型 :不同的列的数据类型可以不同
  • 大小可变 (扩容)
  • 标记轴(行级索引 和 列级索引)
  • 针对行与列进行轴向统计(水平,垂直)
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
import pandas as pd

# 创建一个空的DataFrame
df = pd.DataFrame()
print(df)

# 从列表创建DataFrame
data = [1,2,3,4,5] # 一维列表,5行1列
df = pd.DataFrame(data)
print(df)

data = [['Alex',10],['Bob',12],['Clarke',13]] # 二维列表,3行2列
df = pd.DataFrame(data,columns=['Name','Age'],dtype=float)
print(df)

data = [{'a': 1, 'b': 2},{'a': 5, 'b': 10, 'c': 20}] # 列表字典,键作表头,值作值,不提供值为NaN
df = pd.DataFrame(data)
print(df)

# 直接从字典来创建DataFrame
data = {'Name':['Tom', 'Jack', 'Steve', 'Ricky'],'Age':[28,34,29,42]}
df = pd.DataFrame(data, index=['s1','s2','s3','s4'])
print(df)

data = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']),
'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(data)
print(df)

DataFrame常用属性

属性或方法 编号 描述
axes 1 返回 行/列 标签(index)列表。
columns 2 返回列标签
index 3 返回行标签
dtype 4 返回对象的数据类型(dtype)。
empty 5 如果系列为空,则返回True。
ndim 6 返回底层数据的维数,默认定义:1。
size 7 返回基础数据中的元素数。
values 8 将系列作为ndarray返回。
head(n) 9 返回前n行。
tail(n) 10 返回最后n行。

核心数据结构操作

行和列的增删改查

列访问

DataFrame的单列数据为一个Series。根据DataFrame的定义可以 知晓DataFrame是一个带有标签的二维数组,每个标签相当每一列的列名。

1
2
3
4
5
6
7
8
d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']),
'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd']),
'three' : pd.Series([1, 3, 4], index=['a', 'c', 'd'])}

df = pd.DataFrame(d)

df['one']
df[df.columns[:2]]

列添加

DataFrame添加一列的方法非常简单,只需要新建一个列索引。并对该索引下的数据进行赋值操作即可。

1
2
3
4
import pandas as pd

df['four']=pd.Series([90, 80, 70, 60], index=['a', 'b', 'c', 'd'])
print(df)

注意:创建新的列时,要给出原有dataframe的index,不足时为NaN

列删除

删除某列数据需要用到pandas提供的方法pop,pop方法的用法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import pandas as pd

d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']),
'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd']),
'three' : pd.Series([10, 20, 30], index=['a', 'b', 'c'])}
df = pd.DataFrame(d)
print("dataframe is:")
print(df)

# 删除一列: one
del(df['one'])
print(df)

#调用pop方法删除一列
df.pop('two')
print(df)


#如果想要删除多列呢?
#删除多列 drop 轴向axis=1是必须给的 默认axis=0删除行的 ,不会修改原数据
# inplace=False 不修改原数据
df2 = df.drop(['one','four'],axis=1)
print(df2)

行访问

如果只是需要访问DataFrame某几行数据的实现方式则采用数组的选取方式,使用 “:” 即可:

1
2
3
4
5
6
7
import pandas as pd

d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']),
'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}

df = pd.DataFrame(d)
print(df[2:4])

loc是针对DataFrame索引名称的切片方法。loc方法使用方法如下:

​ 只支持索引名称,不支持索引位置

1
2
3
4
5
6
7
8
import pandas as pd

d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']),
'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}

df = pd.DataFrame(d)
print(df.loc['b'])
print(df.loc[['a', 'b']])

iloc和loc区别是iloc接收的必须是行索引和列索引的位置。iloc方法的使用方法如下:

1
2
3
4
5
6
7
8
import pandas as pd

d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']),
'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}

df = pd.DataFrame(d)
print(df.iloc[2])
print(df.iloc[[2, 3]])

行添加/表合并

1
2
3
4
5
6
7
import pandas as pd

df = pd.DataFrame([['zs', 12], ['ls', 4]], columns = ['Name','Age'])
df2 = pd.DataFrame([['ww', 16], ['zl', 8]], columns = ['Name','Age'])

df = df.append(df2)
print(df)

行删除

使用索引标签从DataFrame中删除或删除行。 如果标签重复,则会删除多行。

1
2
3
4
5
6
import pandas as pd

df = pd.DataFrame([['zs', 12], ['ls', 4]], columns = ['Name','Age'])
# 删除index为0的行
df = df.drop(0)
print(df)

修改DataFrame中的数据 (访问)

更改DataFrame中的数据,原理是将这部分数据提取出来,重新赋值为新的数据。

1
2
3
4
5
6
7
8
9
10
11
import pandas as pd

df = pd.DataFrame([['zs', 12], ['ls', 4]], columns = ['Name','Age'])
df2 = pd.DataFrame([['ww', 16], ['zl', 8]], columns = ['Name','Age'])
df = df.append(df2)
df['Name'][0] = 'Tom'
print(df)

#如果想要通过访问数据,赋值修改的话
# 只能采用通过列,找行的方式,因为底层有赋值的过程
# 如果通过行找列,因为底层没有赋值的过程,所以没有效果,不会修改成功

复合索引

DataFrame的行级索引与列级索引都可以设置为复合索引,表示从不同的角度记录数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
data = np.floor(np.random.normal(85, 3, (6,3)))
"""
注:
1. np.random随机数模块 normal方法,生成一组符合正态分布的随机数
2. 85是期望值, 3是标准差 标准差越大,离散程度越大
3. (6,3) 6行3列的数据
4. np.floor 向下取整
"""

df = pd.DataFrame(data)
index = [('classA', 'F'), ('classA', 'M'), ('classB', 'F'), ('classB', 'M'), ('classC', 'F'), ('classC', 'M')]

df.index = pd.MultiIndex.from_tuples(index)
columns = [('Age', '20+'), ('Age', '30+'), ('Age', '40+')]
df.columns = pd.MultiIndex.from_tuples(columns)

复合索引的访问

1
2
3
4
5
6
7
8
9
10
# 访问行
df.loc['classA']
df.loc['classA', 'F']
df.loc[['classA', 'classC']]

# 访问列
df.Age
df.Age['20+']
df['Age']
df['Age', '20+']

数据加载

IOtools

读HTML中的内容,要求:在HTML中必须要有table标签

处理普通文本

读取文本:read_csv()

csv文件 逗号分隔符文件 数据与数据之间使用逗号分隔

方法参数 参数解释
filepath_or_buffer 文件路径
sep 列之间的分隔符。read_csv()默认为为",", read_table()默认为"\t"
header 默认将首行设为列名。header=None时应手动给出列名。
names header=None时设置此字段使用列表初始化列名。
index_col 将某一列作为行级索引。若使用列表,则设置复合索引。
usecols 选择读取文件中的某些列。设置为为相应列的索引列表。
skiprows 跳过行。可选择跳过前n行或给出跳过的行索引列表。
encoding 编码。

写入文本:dataFrame.to_csv()

方法参数 参数解释
filepath_or_buffer 文件路径
sep 列之间的分隔符。默认为’,’
na_rep 写入文件时dataFrame中缺失值的内容。默认空字符串。
columns 定义需要写入文件的列。
header 是否需要写入表头。默认为True。
index 会否需要写入行索引。默认为True。
encoding 编码。

案例:读取电信数据集。

1
pd.read_csv('../data/CustomerSurvival.csv', header=None, index_col=0)

处理JSON

读取json:read_json()

方法参数 参数解释
filepath_or_buffer 文件路径
encoding 编码。

案例:读取电影评分数据:

1
pd.read_json('../data/ratings.json')

写入json:to_json()

方法参数 参数解释
filepath_or_buffer 文件路径; 若设置为None,则返回json字符串
orient 设置面向输出格式:[‘records’, ‘index’, ‘columns’, ‘values’]

案例:

1
2
3
data = {'Name':['Tom', 'Jack', 'Steve', 'Ricky'],'Age':[28,34,29,42]}
df = pd.DataFrame(data, index=['s1','s2','s3','s4'])
df.to_json(orient='records')

其他文件读取方法参见:https://www.pypandas.cn/docs/user_guide/io.html