数据转换
1.重复数据的移除
duplicated:返回的是Series,输出值为bool值并且True表重复行。
drop_duplicates:返回的是DataFrame,输出的是去除了重复行的新对象,默认保留按照顺序下来第一个遇到的序列。对象名.drop_duplicates([‘列名’]):是对指定部分列进行重复判断,从而过滤指定列中重复出现的项。
对象名.drop_duplicates([‘列名’], keep=‘last’):keep='last’表示保留重复行最后一个。
import pandas as pd
import numpy as np
from pandas import DataFrame, Series
frame = pd.DataFrame({'k1': ['age', 'year'] * 3 + ['year'], 'k2': [1, 1, 2, 3, 3, 4, 4]})
frame
# 输出为
k1 k2
0 age 1
1 year 1
2 age 2
3 year 3
4 age 3
5 year 4
6 year 4
frame.duplicated() # 表示各行是否是重复行
# 输出为
0 False
1 False
2 False
3 False
4 False
5 False
6 True
dtype: bool
frame.drop_duplicates() # 删除重复行并且穿重复的数组会被标为False
# 输出为
k1 k2
0 age 1
1 year 1
2 age 2
3 year 3
4 age 3
5 year 4
frame['k3'] = range(7) # 对象增加新的一列
frame.drop_duplicates(['k1']) # 根据k1列过滤重复项
# 输出为
k1 k2 k3
0 age 1 0
1 year 1 1
frame.drop_duplicates(['k1', 'k2'], keep='last') # 传入keep='last’则保留最后一个
# 输出为
k1 k2 k3
0 age 1 0
1 year 1 1
2 age 2 2
3 year 3 3
4 age 3 4
6 year 4 6
2.用函数或者映射进行数据转换map()
map() 函数是作用于 Series 或 DataFrame 对象的一列,并可以接受函数或含有映射关系的字典型对象。使用map是一种实现元素级转换以及其他数据清理工作的便捷方式。
语法格式为:Series.map(arg,na_action=None)
函数中的参数说明以下:arg:接收 function、dict 或 Series,表示映射关系;
na_action:类似R中的na.action,取值为None或ingore,用于控制遇到缺失值的处理方式,设置为ingore时串行运算过程中将忽略Nan值原样返回。
- 通过数据字典映射
map()方法接受数据字典参数,通过数据字典将数据进行映射。
data = pd.DataFrame({'food': ['bacon', 'pulled pork', 'bacon',
'Pastrami', 'corned beef', 'Bacon',
'pastrami', 'honey ham', 'nova lox'],
'ounces': [4, 3, 12, 6, 7.5, 8, 3, 5, 6]})
data
# 编写一个不同肉类到动物的映射
meat_to_animal = {
'bacon': 'pig',
'pulled pork': 'pig',
'pastrami': 'cow',
'corned beef': 'cow',
'honey ham': 'pig',
'nova lox': 'salmon'
}
lowercased = data['food'].str.lower() #使用Series的str.lower方法,将各个值转换为小写
# lowercased
data['animal'] = lowercased.map(meat_to_animal)
data
# 输出为
food ounces animal
0 bacon 4.0 pig
1 pulled pork 3.0 pig
2 bacon 12.0 pig
3 Pastrami 6.0 cow
4 corned beef 7.5 cow
5 Bacon 8.0 pig
6 pastrami 3.0 cow
7 honey ham 5.0 pig
8 nova lox 6.0 salmon
- lambda函数映射
map()方法可以用lambda函数的方式进行值的映射。
data['food'].map(lambda x: meat_to_animal[x.lower()])
# 输出为
0 pig
1 pig
2 pig
3 cow
4 cow
5 pig
6 cow
7 pig
8 salmon
Name: food, dtype: object
- 通用函数映射
map()方法还可以接收自定义通用的函数进行值的映射。
data_frame = pd.DataFrame({'student_id':['ox1', 'ox2', 'ox3', 'ox4', 'ox5', 'ox6'],
'language_score':[90, 88, 96, 89, 97, 99]})
# data_frame
def score(x):
score_class='良好'
if x>95:
score_class='优秀'
return score_class
data_frame['等级']=data_frame['language_score'].map(score)
data_frame
# 输出为
student_id language_score 等级
0 ox1 90 良好
1 ox2 88 良好
2 ox3 96 优秀
3 ox4 89 良好
4 ox5 97 优秀
5 ox6 99 优秀
3.替换值replace()
如果要对全DataFrame或者是Series数据集中的数据进行某种替换,map()可能需要对数据集中的每个列都进行map()操作才可以,但是replace方法可以一次性替换掉DataFrame或者是Series中所有的数据。
单值替换:
对象.replace(要替换的值,替换值)
多值替换:
对象.replace([要替换的值列表],替换值)
对象.replace([要替换的值列表],[替换值列表])
对象.replace({要替换的值:替换值})
- 通过fillna方法填充缺失值来看作替换值的一种特殊情况
data = pd.Series([1., -999., 2., -999., -1000., 3.])
# data
data.replace(-999, np.nan) # 用replace来产生一个新的Series(除非传入inplace=True)
# 输出为
0 1.0
1 NaN
2 2.0
3 NaN
4 -1000.0
5 3.0
dtype: float64
data.replace([-999, -1000], np.nan) # 一次性替换多个值,要替换的值组成列表和一个替换值
# 输出为
0 1.0
1 NaN
2 2.0
3 NaN
4 NaN
5 3.0
dtype: float64
data.replace([-999, -1000], [np.nan, 0]) # 让每个值有着不同的替换值,可以传递一个替换列表
data.replace({-999: np.nan, -1000: 0}) # 传入的参数也可以是字典
# 输出为
0 1.0
1 NaN
2 2.0
3 NaN
4 0.0
5 3.0
dtype: float64
4.重命名rename()
在数据处理的过程有时候需要对列索引或是行索引进行重命名。
列索引:对象.rename(columns={‘原索引’:‘重命名索引’}) ,一个典型的例子就是对于数据的检索或其他操作对象[column] 对于任意列名均有效,但是 对象.column只在列名是有效的Python变量名时才有效。
行索引:对象.rename(index={‘原索引’:‘重命名索引’})的方式进行重命名。
行和列同时索引:对象.rename(index={‘原索引’:‘重命名索引’},columns={‘原索引’:‘重命名索引’} )
# 举一个例子
data = pd.DataFrame(np.arange(12).reshape((3, 4)),
index=['Ohio', 'Colorado', 'New York'],
columns=['one', 'two', 'three', 'four'])
transform = lambda x: x[:4].upper()
data.index.map(transform) # 轴索引也有一个map方法
# 输出为
Index(['OHIO', 'COLO', 'NEW '], dtype='object')
data.index = data.index.map(transform) # 赋值给index,对DataFrame进行就地修改
data
# 输出为
one two three four
OHIO 0 1 2 3
COLO 4 5 6 7
NEW 8 9 10 11
data.rename(index=str.title, columns=str.upper) # 想要创建数据集的转换版(而不是修改原始数据)
ONE TWO THREE FOUR
Ohio 0 1 2 3
Colo 4 5 6 7
New 8 9 10 11
- inplace=True参数用于更新作用于本数据集,而不是返回一个新的数据集
- 列索引
data.rename(columns={'one': 'one_1'}, inplace=True)
data.query('one_1 > 0') # 查询one_1大于0的数据
# 输出为
one_1 two three four
COLO 4 5 6 7
NEW 8 9 10 11
若出现python变量命名不规范,就会出现data.columns调用时报列名不是有效的python变量名
data.rename(columns={'one': '一'}, inplace=True)
data.query('一 > 0')
# 报错为:UndefinedVariableError: name '一' is not defined
- 行索引
data.rename(index={'New York': 'New_index'}, inplace=True)
data
# 输出为
one two three four
Ohio 0 1 2 3
Colorado 4 5 6 7
New_index 8 9 10 11
- 同时索引
data.rename(index={'OHIO': 'INDIANA'},
columns={'three': 'peekaboo'}) # rename可以结合字典型对象实现对部分轴标签的更新
# 输出为
one two peekaboo four
INDIANA 0 1 2 3
COLO 4 5 6 7
NEW 8 9 10 11
5.检测和过滤异常值
异常值的检测和过滤运算在很大程度上就是数组运算。
对象[np.函数方法(对象)]
data = pd.DataFrame(np.random.randn(1000, 4))
# data
# data.describe()
col = data[2] # 输出一个Series
col[np.abs(col) > 3] # 输出某列中绝对值大小超过3的值
data[(np.abs(data) > 3).any(1)] # 输出绝对值大于3,用any(1)方法来输出含有-3的值
data[np.abs(data) > 3] = np.sign(data) * 3 # 将值限制在区间-3到3以内
# data.describe()
np.sign(data).head() # np.sign(data)可以生成1和-1的值
6.计算指标/哑变量
一种常用于统计建模或机器学习的转换方式是:将分类变量(categorical variable)转换为“哑变量”或“指标矩阵”。
- 哑变量
加前缀:pd.get_dummies(对象[‘指标’], prefix=‘前缀’) 将指标中所有变量名都加上前缀。
插入原对象前面:对象的列名.jion(要插入的对象)
df = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'b'],
'data1': range(6)})
# df
pd.get_dummies(df['key']) # 按照index顺序下来,出现为1,不出现为0
dummies = pd.get_dummies(df['key'], prefix='key')
# dummies
df[['data1']].join(dummies) # 将新的一列插入到原对象前面
# dummies['data1'] = range(6) # 普通插入列项,插入到原对象的后面
# 输出为
data1 key_a key_b key_c
0 0 0 1 0
1 1 0 1 0
2 2 1 0 0
3 3 0 0 1
4 4 1 0 0
5 5 0 1 0
- 对统计应用:结合get_dummies和其它pandas方法如pandas.cut()的离散化函数
np.random.seed(1234) # 设置seed函数参数后,无论执行多少次随机函数都相等
values = np.random.rand(10)
values
# 输出为
'''
array([0.35781727, 0.50099513, 0.68346294, 0.71270203, 0.37025075,
0.56119619, 0.50308317, 0.01376845, 0.77282662, 0.88264119])
'''
abs = [0, 0.2, 0.4, 0.6, 0.8, 1]
pd.get_dummies(pd.cut(values, abs)) # pd.cut离散化函数,在这里把abs的值分成不同的值域
# 输出为
(0.0, 0.2] (0.2, 0.4] (0.4, 0.6] (0.6, 0.8] (0.8, 1.0]
0 0 1 0 0 0
1 0 0 1 0 0
2 0 0 0 1 0
3 0 0 0 1 0
4 0 1 0 0 0
5 0 0 1 0 0
6 0 0 1 0 0
7 1 0 0 0 0
8 0 0 0 1 0
9 0 0 0 0 1
np.random.seed()函数中的参数可以选择任何一个数,它的功能是使设有相同参数的seed函数之后的随机数都相等。