数据存在的形式
- 文件:csv, excel, txt……
- 数据库:mysql, access, sql server……
导入 CSV 文件
pandas 包中的 read_csv 函数:read_csv(file, encoding)
from pandas import read_csv
# 相对地址
df = read_csv(
r'1.csv'
)
df = read_csv(
'./1.csv'
)
# 绝对地址
df = read_csv(
r'C:\Users\lian\Desktop\python\4.1\1.csv'
)
df = read_csv(
'C:/Users/lian/Desktop/python/4.1/1.csv'
)
导入文本文件
pandas 包中的 read_table 函数:read_table(file,names=[列名1,列名2,...],sep="",encoding,...)
参数 | 注释 |
---|---|
names | 指定列名,默认以文件中第一行为列名 |
sep | 分隔符,默认为空,表示默认导入为一列。当文本中以,隔开哥哥元素时,需指定为, |
from pandas import read_table
df = read_table(
'2.txt',
names=['age', 'names'],
sep=','
)
当导入中文时存在问题的时候,可以设置 engine = 'python'
解决问题
df = read_table(
'2.txt',
names=['age', 'names'],
sep=',',
encoding='UTF-8',
engine='python'
)
导入 Excel 文件
pandas 包中的 read_excel 函数:read_excel(file,sheetname,names)
参数 | 注释 |
---|---|
sheetname | 读取哪一个 sheet |
names | 指定列名,默认以文件中第一行为列名 |
from pandas import read_excel
df = read_excel(
'3.xlsx',
sheetname='data'
)
dataFrame 导出为 csv 文件
to_csv 函数:dataFrame.to_csv(file,sep="",index,header)
参数 | 注释 |
---|---|
index | 是否导出行序号,默认为 True。实际一般设置为 False |
header | 是否导出列名,默认为 True |
from pandas import DataFrame
df = DataFrame({
'age':[21,22,23],
'name':['ken','john','jimi']
})
# 导出到当前目录下名为 test.csv 的文件
df.to_csv(
'test.csv',
index=False
)
重复值处理
把 dataFrame 中,行相同的数据只保留一行
相关函数:
-
dataFrame.duplicated()
找出或只按指定列找出重复的行,根据是否重复返回元素值为 boolean 的 Series,表示是否重复(重复为 True) -
dataFrame.drop_duplicates()
删除或值考虑某一列的值删除重复的行,返回新的 DataFrame
from pandas import read_csv
# 导入数据
df = read_csv('data.csv')
# 找出行重复的位置。返回一个 Series,值为 boolean ,表示每行是否重复,当行所有元素的值都重复时,返回 True
dIndex = df.duplicated()
# 根据某些列,找出重复的位置
dIndex = df.duplicated('id')
# 当指定多列时,是 and 关系,即所有指定列都重复了才为 True
dIndex = df.duplicated(['id', 'key'])
#根据返回值,把重复数据提取出来
df[dIndex]
#直接删除重复值
#默认根据所有的列,进行删除
newDF = df.drop_duplicates()
#当然也可以指定某一列,进行重复值处理
newDF = df.drop_duplicates('id')
缺失值的处理
缺失值的处理方式:1. 数据补齐;2. 删除对应缺失行;3. 不处理
相关函数:
dataFrame.isnull()
dataFrame.any(axis=1)
dataFrame.fillna('填充 nan 的值')
dataFrame.dropna()
from pandas import read_csv
# 导出数据
# data.csv 本身已有缺失值
df = read_csv(
'data.csv'
)
# data2.csv 无缺失值,na_values=['a','b'] 表示将元素值为 a 或 b 的元素值设置为 nan
df = read_csv(
'data2.csv',
na_values=['a','b']
)
# 找出空值的位置
# isnull() 函数返回一个同结构的 DataFrame(大小、列名、索引相同),但元素值以是否为 null ( nan ) 设置为 boolean 值
isNA = df.isnull()
# 获取出空值所在的行
# isNA.any(axis=1) 返回一个 boolean 值的 Series ,当 axis=1 时表示 isNA 的每一行是否有存在值为 True 的元素,只要有则对应的 boolean 为 True
# 再根据 dataFrame[series] 过滤出有空值的行
df[isNA.any(axis=1)]
# 获取根据某一列或多列中存在空值所在的行
# isNA[['key']] 得到的是 DataFrame,isNA['key'] 得到的是 Series
df[isNA[['key']].any(axis=1)]
# 获取 key 或 value 列中空值所在的行
df[isNA[['key', 'value']].any(axis=1)]
# 将 df 中元素值为 nan 的值设置为 '未知'
df.fillna('未知')
# 直接删除空值。将有空值的该行删除
newDF = df.dropna()
空格值的处理
相关函数:
-
str.strip()
清除字符型数据左右的空格(lstrip() 清除左边,rstrip() 清除右边) -
series.str.xxx
表示对 series 中所有字符元素做处理
from pandas import read_csv
df = read_csv(
'data.csv'
)
# 处理 name 字段中元素的字符
newName = df['name'].str.lstrip()
newName = df['name'].str.rstrip()
newName = df['name'].str.strip()
df['name'] = newName
字段抽取
字段抽取是根据指定字段下的一组数据的开始和结束位置,抽取形成新的列
相关函数:
-
series.astype(str)
对 series 中所有元素转化为 str 类型 -
str.slice(0, 3)
对 str 做切片
字段截取函数:slice(start, stop)
from pandas import read_csv
df = read_csv(
'data.csv'
)
# 将 df 数据框中 tel 字段的元素值的类型转化为 str 类型,并赋值回去
df['tel'] = df['tel'].astype(str)
#运营商
bands = df['tel'].str.slice(0, 3)
#地区
areas = df['tel'].str.slice(3, 7)
#号码段
nums = df['tel'].str.slice(7, 11)
#赋值回去
df['bands'] = bands
df['areas'] = areas
df['nums'] = nums
字段拆分
字段拆分指按照固定的字符,拆分已有字符串
相关函数:
str.split(sep, n, expand)
参数 | 注释 |
---|---|
sep | 分割的字符串所用的子字符串 |
n | 分割为多少列。当为 1 时,分割为两列,即只分割找到的第一个 sep |
expand | 是否展开为数据框,默认 False。当为 True 返回 DataFrame,当为 False 返回 Series |
from pandas import read_csv
df = read_csv(
'data.csv'
)
newDF = df['name'].str.split(' ', 1, True)
newSe = df['name'].str.split(' ', 2, True)
# 默认分割后的列名为 0,1,...
newDF.columns = ['band', 'name']
记录抽取
记录抽取指根据一定的条件,对数据进行抽取
相关函数:
dataFrame[condition]
condition 为一 Series,元素数量与 dataFrame 行数相等,元素为 boolean 值,决定是否抽取记录
常用的条件类型:
- 比较运算
> < >= <= !=
- 范围运算
between(left, right)
- 空值匹配
pandas.isnull(column)
- 字符匹配
str.contains(pattern, na=False)
- 逻辑运算
& | not
如df[(df.comments >= 1000) & (df.comments <= 10000)]
等价于df[df.comments.between(1000, 10000)]
import pandas
df = pandas.read_csv(
'data.csv', sep="|"
)
#单条件
df[df.comments>10000]
#多条件
df[df.comments.between(1000, 10000)]
#过滤空值所在行
df[pandas.isnull(df.title)]
#根据关键字过滤
df[df.title.str.contains('台电', na=False)]
#~为取反
df[~df.title.str.contains('台电', na=False)]
#组合逻辑条件
df[(df.comments>=1000) & (df.comments<=10000)]
随机抽样
随机抽样指随机从数据中,按照一定的函数或者比例抽取数据
相关函数:
numpy.random.seed(seed=2)
设置随机种子
dataFrame.sample(n, frac, replace=False)
参数 | 注释 |
---|---|
n | 按个数抽样 |
frac | 按百分比抽样 |
replace | 是否可放回抽样。默认 False 不可放回 |
import numpy
import pandas
data = pandas.read_csv(
'data.csv'
)
#设置随机种子
numpy.random.seed(seed=2)
#按照个数抽样
data.sample(n=10)
#按照百分比抽样
data.sample(frac=0.02)
#是否可放回抽样
data.sample(n=10, replace=True)
典型抽样 之 分层抽样:
按照某一字段将 dataFrame 分为几组,并在每个分组抽取样本
相关函数:
-
dataFrame.groupby('class', group_keys)
根据对应的字段的值将 dataFrame 分组,从而获取 DataFrameGroupBy 实例。group_keys
指当 DataFrameGroupBy 实例调用.apply()
函数时,是否添加分组字段的值到索引以便区分。DataFrameGroupBy 实例有属性:-
dataFrameGroupBy.groups
获取一个 dict,该 dict 以原 dataFrame 所指定 groupby 的字段的值为 key ,value 为对应值的行的索引的集合 -
dataFrameGroupBy.apply(funcName,...)
将分组后的每个 dataFrame 传入指定的函数作处理,该函数定义类似为def funcName(dataFrame, *args, **kv)
,参数dataFrame
指传进的 dataFrame ,该 dataFrame 与一般 dataFrame 多了一个属性.name
,指分组对应的字段的值,函数返回一个同参数一样结构的dataFrame。apply()
函数最终返回一个 DataFrame,作为各个分组应用处理后的 dataFrame 的重新整合
-
# 按 class 列进行分组,得到一个分组对象
gbr = data.groupby("class")
# 获取所有分组字典
gbr.groups
# 定义一个字典,指明每组需要抽取的个数
typicalNDict = {
1: 2,
2: 4,
3: 6
}
# 定义分层抽样的方法
def typicalSampling(group, typicalNDict):
name = group.name
n = typicalNDict[name]
return group.sample(n=n)
# 使用分组对象的 apply 方法
result = data.groupby(
'class', group_keys=False
).apply(typicalSampling, typicalNDict)
# ==================================================
# 按百分比的方式
typicalFracDict = {
1: 0.2,
2: 0.4,
3: 0.6
}
def typicalSampling(group, typicalFracDict):
name = group.name
frac = typicalFracDict[name]
return group.sample(frac=frac)
result = data.groupby(
'class', group_keys=False
).apply(typicalSampling, typicalFracDict)
记录合并 —— 数据框的合并
记录合并指将两个以上结构相同或不同的数据框,合并成一个数据框
相关函数:
-
concat([df1, df2,...])
指记录的合并,即假设 df1 有m条记录,df2 有n条记录,则合并后有 m+n 条记录,索引为原来的索引,对于不同 DataFrame 字段不同的问题,则缺失的字段的值以 nan 填充
import pandas
from pandas import read_csv
data1 = read_csv(
'data1.csv', sep="|"
)
data2 = read_csv(
'data2.csv', sep="|"
)
data3 = read_csv(
'data3.csv', sep="|"
)
data = pandas.concat([data1, data2, data3])
# 当列名不一样时,合并后数据缺失部分填充为 nan
data = pandas.concat([
data1[[0, 1]],
data2[[1, 2]],
data3[[0, 2]]
])
字段合并 —— 列的合并
字段合并指将同意数据框中的不同列进行合并,形成新的列
字段合并方法:x = x1 + x2 + ... (x 指数据列,Series)
相关函数:
-
dataFrame.astype(str)
将整个 dataFrame 元素的值的类型转化为 str
from pandas import read_csv
df = read_csv(
'data.csv',
sep=" ",
names=['band', 'area', 'num']
)
df = df.astype(str)
tel = df['band'] + df['area'] + df['num']
df['tel'] = tel
字段匹配
字段匹配指根据各表共有的关键字段,把各表所需的记录一一对应起来。即把两个 dataFrame 关联起来
相关函数:
merge(x,y,left_on,right_on)
参数 | 注释 |
---|---|
x | 第一个数据框 |
y | 第二个数据框 |
left_on | 第一个数据框用于匹配的列 |
right_on | 第二个数据框用于匹配的列 |
how | merge 方式 |
import pandas
items = pandas.read_csv(
'data1.csv',
sep='|',
names=['id', 'comments', 'title']
)
prices = pandas.read_csv(
'data2.csv',
sep='|',
names=['id', 'oldPrice', 'nowPrice']
)
# 默认只是保留连接得上的部分
# 类似数据库操作的 inner join
itemPrices = pandas.merge(
items,
prices,
left_on='id',
right_on='id'
)
# 即使连接不上,也保留左边没连上的部分
# 类似数据库操作的 left join
itemPrices = pandas.merge(
items,
prices,
left_on='id',
right_on='id',
how='left'
)
# 即使连接不上,也保留右边没连上的部分
# 类似数据库操作的 right join
itemPrices = pandas.merge(
items,
prices,
left_on='id',
right_on='id',
how='right'
)
# 即使连接不上,也保留所有没连上的部分
# 类似数据库操作的 full join
itemPrices = pandas.merge(
items,
prices,
left_on='id',
right_on='id',
how='outer'
)
简单计算
简单计算指通过对已有字段进行加减乘除等运算,得出新的字段
import pandas
data = pandas.read_csv(
'data.csv',
sep="|"
)
data['total'] = data.price*data.num
#注意,用点的方式,虽然可以访问,但是并没有组合进数据框中
data = pandas.read_csv(
'data.csv',
sep="|"
)
data.total = data.price*data.num
# 错误,因为 data 没有对应的字段 total
data.total
数据标准化
数据标准化指将数据按比例缩放,使之落入到特定区间
0-1 标准化计算
相关函数:
series.min()
series.max()
-
series.describe()
返回一个 Series ,索引为 count / mean / std / min / 25% / 50% / 75% / max,保存着对应的值
import pandas
data = pandas.read_csv(
'data.csv'
)
# round 取小数点后两位
data['scale'] = round(
(
data.score-data.score.min()
)/(
data.score.max()-data.score.min()
)
, 2
)
数组分组
数组分组指根据数据分析对象的特征,按照一定的数值指标,把数据分析对象划分为不通的区间进行研究,以揭示其内在的联系和规律性
主要针对如年龄这个字段,值比较分散,我们可以将其划分为如 [ '20以下', '20到40', '40到60', '60到80', '80到100', '100以上' ] ,以便做进一步的分析
相关函数:
-
pandas.cut(series, bins, right=True, labels=NULL)
返回一个 Series
参数 | 注释 |
---|---|
series | 需要分组的数据 |
bins | 分组的划分数组 |
right | 分组的时候,右边是否闭合,默认 True。即如 (0, 10] 还是 [0, 10) |
labels | 分组的自定义标签,可以不自定义 |
import pandas
data = pandas.read_csv(
'data.csv',
sep='|'
)
# 定义一个分组区间
bins = [
min(data.cost)-1, 20, 40, 60,
80, 100, max(data.cost)+1
]
data['cut'] = pandas.cut(
data.cost,
bins
)
data['cut'] = pandas.cut(
data.cost,
bins,
right=False
)
labels = [
'20以下', '20到40', '40到60',
'60到80', '80到100', '100以上'
]
data['cut'] = pandas.cut(
data.cost, bins,
right=False, labels=labels
)
时间处理
时间转换,str => datetime
时间转换函数:
-
pandas.to_datetime(datetimeData, format)
当 datetimeData 为 str 时,返回一个 datetime,当为 series 时,返回一个 series pandas.datetime.strptime(dates, '%Y%m%d')
属性 | 注释 |
---|---|
%Y | 年份 |
%m | 月份 |
%d | 日期 |
%H | 小时 |
%M | 分钟 |
%S | 秒钟 |
时间格式化,datetime => str
-
series.dt
表示对 series 所有 datatime 类型的元素做处理 -
dateTimeStr = datetime.strftime(format)
时间格式化函数
时间属性抽取,指从日期格式里面,抽取出需要的部分属性
时间属性抽取语法:datetime.property
property 可选项 | 注释 |
---|---|
second | |
minute | |
hour | |
day | |
month | |
year | |
weekday |
import pandas
data = pandas.read_csv(
'data.csv',
encoding='utf8'
)
data['时间'] = pandas.to_datetime(
data.注册时间,
format='%Y/%m/%d'
)
data['格式化时间'] = data.时间.dt.strftime('%Y-%m-%d')
data['时间.年'] = data['时间'].dt.year
data['时间.月'] = data['时间'].dt.month
data['时间.周'] = data['时间'].dt.weekday
data['时间.日'] = data['时间'].dt.day
data['时间.时'] = data['时间'].dt.hour
data['时间.分'] = data['时间'].dt.minute
data['时间.秒'] = data['时间'].dt.second
时间抽取
时间抽取指按一定条件,对时间格式的数据进行抽取
相关函数:
- 根据索引进行抽取
-
dataFrame.ix
是 dataFrame 关于 index 的相关操作 -
dataFrame.ix[start: end]
表示获取 index 区间的行 -
dataFrame.ix[dates]
表示获取指定 list 的行
-
- 根据时间列进行抽取
dataFrame[condition]
import pandas
data = pandas.read_csv(
'data.csv',
encoding='utf8'
)
# 时间相关处理函数,str ==> datetime
dateparse = lambda dates: pandas.datetime.strptime(dates, '%Y%m%d')
# parse_dates 指定需要进行时间处理的字段,date_parser 指定时间处理函数,index_col 所指定的列作为索引
data = pandas.read_csv(
'data.csv',
encoding='utf8',
parse_dates=['date'],
date_parser=dateparse,
index_col='date'
)
#根据索引进行抽取
import datetime
# 创建两个 datatime 类型实例
dt1 = datetime.date(year=2016,month=2,day=1);
dt2 = datetime.date(year=2016,month=2,day=5);
# 切片
data.ix[dt1: dt2]
# list ,指定要获取的 index
data.ix[[dt1,dt2]]
#根据时间列进行抽取
data = pandas.read_csv(
'data.csv',
encoding='utf8',
parse_dates=['date'],
date_parser=dateparse,
)
data[(data.date>=dt1) & (data.date<=dt2)]
虚拟变量
虚拟变量,也叫哑变量和离散特征编码,可用来表示分类变量、非数量因素可能产生的影响
虚拟变量的取值有两种:
- 离散特征的取值之间有大小的意义,如尺寸(L XL S);
- 离散特征的取值之间没有大小的意义,如颜色(红 蓝 绿)
离散特征的取值之间有大小的意义的处理函数:pandas.Series.map(dict)
、series.map(dict)
dict 以 series 的值为 key ,以要映射的值为 value,返回一个 Series
离散特征的取值之间没有大小的意义的处理函数:pandas.get_dummies(data, prefix=None, prefix_sep='_'. dummy_na=False, columns=None, drop_first=False)
属性 | 注释 |
---|---|
data | 要处理的 DataFrame |
prefix | 列名的前缀,在多个列有相同的离散项时使用 |
prefix_sep | 前缀和离散值的分隔符,默认为下划线 |
dummy_na | 是否把 nan 值作为一个离散值进行处理,默认不处理 |
columns | 要处理的列名,如果不指定,则默认处理所有列 |
drop_first | 是否从备选项中删除第一个,建模的时候为避免共线性使用 |
import pandas
data = pandas.read_csv(
'data.csv',
encoding='utf8'
)
# 可以看出 Education Level 取值之间有大小的意义,我们可以将之与具体的数值映射
data['Education Level'].drop_duplicates()
"""
博士后 Post-Doc
博士 Doctorate
硕士 Master's Degree
学士 Bachelor's Degree
副学士 Associate's Degree
专业院校 Some College
职业学校 Trade School
高中 High School
小学 Grade School
"""
educationLevelDict = {
'Post-Doc': 9,
'Doctorate': 8,
'Master\'s Degree': 7,
'Bachelor\'s Degree': 6,
'Associate\'s Degree': 5,
'Some College': 4,
'Trade School': 3,
'High School': 2,
'Grade School': 1
}
data['Education Level Map'] = data[
'Education Level'
].map(
educationLevelDict
)
# 可以看出 Gender 取值之间没有大小的意义
data['Gender'].drop_duplicates()
"""
男 Male
女 Female
空值 nan
"""
# 这里离散值有 Male Female(忽略 nan),加上前缀和分隔符,生成两列 'Gender_Male' 、'Gender_Female' ,以 0或1 表示在原列中是否有对应的值,返回的 dataFrame 不包含原 'Gender'
dummies = pandas.get_dummies(
data,
columns=['Gender'],
prefix=['Gender'],
prefix_sep="_",
dummy_na=False,
drop_first=False
)
dummies['Gender'] = data['Gender']