数据清洗与准备

1. 处理缺失值

缺失值:np.nan;None;

1.1 过滤缺失值——dropna

  1. Series 对象:
from numpy import nan as NA
data = pd.Series([1, NA, 3.5, NA, 7])
data.dropna() == data[data.notnull()]	#两种过滤方法是等价的
  1. DataFrame 对象:
data = pd.DataFrame([[1., 6.5, 3.], [1., NA, NA], [NA, NA, NA], [NA, 6.5, 3.]])
cleaned_1 = data.dropna()		#默认删除包含缺失值的行
cleaned_2 = data.dropna(axis=1)		#删除包含缺失值的列
cleaned_3 = data.dropna(how='all')	#删除所有值都为 NA 的行
cleaned_4 = data.dropna(thresh=2)	#设置阈值,保留含有2个及以下NA值的行

1.2 补全缺失值——fillna

fill_1 = df.fillna(0)				#使用一个常数来替换缺失值
fill_2 = df.fillna({1: 0.5, 2: 0})		#为不同的列设定不同的填充值
fill_3 = df.fillna(0, inplace=True)		#fillna 默认返回新的对象,使用 inplace 参数修改原对象
fill_4 = df.fillna(method='ffill', limit=2)	#向前插值(默认值),(bfill为向后插值)并设定最大填充范围
fill_5 = df.fillna(method='bfill', axis=1)	#axis默认为0,按行插值,1为按列插值

2. 数据转换

2.1 删除重复值

df = pd.DataFrame({'k1': ['one', 'two'] * 3 + ['two'], 'k2': [1, 1, 2, 3, 3, 4, 4]})
is_duplicated = df.duplicated()		#返回一个布尔型 Series,反映每一行是否重复
droped = df.drop_duplicates()		#返回数组中未重复的部分
# 以上都是默认对列进行操作
droped_1 = df.drop_duplicates('k1')	#基于'k1'列去除重复值
droped_last = df.drop_duplicates(['k1'], keep='last')	#默认是保留第一个观测到的值,keep='last'指定返回最后一个

2.2 使用函数或者映射进行数据转换——map

'''关于肉类的假设数据,需求添加一列用于表明每种食物的动物类型'''
data = pd.DataFrame({'food': ['bacon', 'pulled pork', 'bacon', 
			     'Pastrami', 'corned beef', 'Bacon',
			     'pastrami', 'honey ham', 'nova lox']})
# 使用字典映射
meat_to_animal = {
	'bacon': 'pig',
	'pulled pork': 'pig',
	'pastrami': 'cow',
	'corned beef': 'cow',
	'honey ham': 'pig',
	'nova lox': 'salmon'
    }
data['animal'] = data['food'].str.lower().map(meat_to_animal)
# 使用匿名函数
data['animal'] = data['food'].map(lambda x:meat_to_animal[x.lower()])

2.3 替代值——replace

data= pd.Series([1., -999, 2, -999, -1000, 3])
replaced_1 = data.replace(-999, np.nan)			#使用 NA 替代 -999
replaced_2 = data.replace([-999, -1000], np.nan)	#一次替代多个值
replaced_3 = data.replace([-999, -1000], [np.nan, 0])	#不同值替代不同值
replaced_4 = data.replace({-999: np.nan, -1000: 0})	#也可使用字典作为参数传递

2.4 重命名索引

  1. 使用函数或映射——map:
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 = data.index.map(transform)		# 在原数组上修改索引
  1. 使用 rename:默认不修改原数据
data_1 = data.rename(index=str.title, columns=str.upper)	#使用函数转换
data_2 = data.rename(index={'OHIO': 'INDIANA'},
			columns = {'three': 'peekaboo'}, inplace=True)	#结合字典型对象,为轴标签的子集提供新的值,并修改原数组

2.5 离散化和分箱——cut & qcut

  1. cut 的基本用法:
'''将一群人的年龄分组'''
ages = [20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32]
bins = [18, 25, 35, 60, 100]			#分组的区间
cats = pd.cut(ages, bins)

'''输出如下:
[(18, 25], (18, 25], (18, 25], (25, 35], (18, 25], ..., (25, 35], (60, 100], (35, 60], (35, 60], (25, 35]]
Length: 12
Categories (4, interval[int64]): [(18, 25] < (25, 35] < (35, 60] < (60, 100]]
'''

cats.codes

'''输出如下:
array([0, 0, 0, 1, 0, 0, 2, 1, 3, 2, 2, 1], dtype=int8)
'''

cats.categories

'''输出如下:
IntervalIndex([(18, 25], (25, 35], (35, 60], (60, 100]],
              closed='right',
              dtype='interval[int64]')
'''

counts = pd.value_counts(cats)			#各箱中包含的值的数量

'''输出如下:
(18, 25]     5
(35, 60]     3
(25, 35]     3
(60, 100]    1
dtype: int64
'''

返回的是一个 Categories 对象,可以当作是一个表示箱名的字符串数组,每个值代表原数组中所对应的值处于分组的哪个区间;codes 属性表示每个值代表原数组中所对应的值处于分组的第几个区间,categories 属性表示区间的数据标签

  1. cut 默认区间的左侧开放(小括号),右侧封闭(中括号,包括边),指定哪边封闭:
cut_left = pd.cut(ages, bins, right=False)
  1. labels 参数传入自定义箱名
group_names = ['Youth', 'YoungAdult', 'MiddleAged', 'Senior']
cut_with_names = pd.cut(ages, bins, labels=group_names)
  1. 传入整数代替显式的箱边,根据值的最大值和最小值来以及箱的个数来决定分组区间(均匀分布的数据会使每个箱具有相同数量的数据,其他分布一般来说不会)
data = np.random.rand(20)
four_box = pd.cut(data, 4, precision=2)		#precision=2 选项将十进制精度限制在两位
  1. qcut 的用法:qcut 基于样本分位数进行分箱,因此 qcut 可获得等长的箱
data = np.random.randn(1000)
cats = np.qcut(data, 4)			# 切成 4 份
cats_2 = pd.qcut(data, [0, 0.1, 0.5, 0.9, 1.])	#自定义分位数

2.6 检测和过滤异常值

'''检测数组中绝对值大于 3 的值'''
data = pd.DataFrame(np.random.randn(1000, 4))
col = data[1]
col_3 = col[np.abs(col) > 3]			#找出一列中绝对值大于 3 的值
data_3 = data[(np.abs(data) > 3).any(1)]	#找出所有含有绝对值大于 3 的行,axis=1 代表沿着列标签执行方法(消灭列标签)
data[np.abs(data) > 3] = np.sign(data) * 3	#np.sign(data)根据data的值的正负生成-1与1

2.7 置换和随机抽样

  1. 使用 np.random.permutation 对 DataFrame 中的行进行置换(随机重排序):
df = pd.DataFrame(np.arange(5 * 4).reshape((5, 4)))
sampler = np.random.permutation(5)	#产生一个长度为5的表示新顺序的整数数组
df.take(sampler)			#整数数组可以用在基于 iloc 的索引或等价的 take 函数中,以实现对原数组的重排序
sample_1 = df.sample(n=3)		#随机抽3行,不能重复选择
sample_2 = df.sample(n=4, replace=True)	#允许重复选择

2.8 计算指标/虚拟变量

  1. 假设 DataFrame 中的一列有 k 个不同的值,使用 get_dummies 函数衍生一个 k 列值为 1 和 0 的矩阵或 DataFrame:
df = pd.DataFrame({'key': ['b', 'b', 'a', 'c', 'a', 'c'],
		'data1': range(6)})
dummies = pd.get_dummies(df['key'])

'''输出如下:
  a b c
0 0 1 0
1 0 1 0
2 1 0 0
3 0 0 1
4 1 0 0
5 0 0 1  
'''
  1. 在指标 DataFrame 的列上加入前缀,然后与其他数据合并:
dummies_2 = pd.get_dummies(df['key'], prefix='key')
df_with_dummy = df[['data1']].join(dummies_2)

'''输出如下:
  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     0     1
'''
  1. 将 get_dummies 和 cut 等离散化函数结合使用:
values = np.random.rand(10)
bins = [0, 0.2, 0.4, 0.8, 1]
dummies = pd.get_dummies(pd.cut(values, bins))

3. 字符串操作

3.1 字符串对象方法

方法描述
str_1.count(str_2)返回子字符串(str_2)在字符串(str_1)中的非重叠出现次数
str_1.endswith(str_2)如果 str_1 以 str_2 结尾则返回 True
str_1.startswith(str_2)如果 str_1 以 str_2 开头则返回 True
str.join(list)使用 str_1 作为间隔符,用于粘合字符串序列 list
str_1.index(str_2)如果在 str_1 中找到子字符串 str_2,则返回 str_2 中第一个字符的位置;如果找不到则引发 ValueError
str_1.find(str_2)返回 str_1 中第一个出现 str_2 的第一个字符的位置,与 index 类似,但找不到则返回 -1
str_1.rfind(str_2)与 find 类似,但返回最后一个出现 str_2 的第一个字符的位置
str.replace(old_str, new, max)使用 new 替换 str 中的 old_str,可选参数 max 指定最多替换次数
str.strip(), str.rstrip(), str.lstrip()修剪空白,包括换行符;相当于对每个元素进行x.strip()(包括 rstrip, lstrip)
str_1.split(str_2)使用 str_2 分隔符将字符串 str_1 拆分为子字符串的列表
str.lower()大写字母转换为小写字母
str.upper()小写字母转换为大写字母
str.casefold()将字符转换为小写,适用于所有存在大小写的字符
str.ljust(int), str.rjust(int)左对齐或右对齐;用空格(或一些其他字符)填充字符串的相反侧以返回具有最小宽度的字符串

3.2 正则表达式——re 模块

  1. 例:将含有多种空白字符(制表符、空格、换行符)的字符串拆分开:
import re
text = 'foo	far\t baz  \tqux'
result = re.split('\s+', text)			#描述一个或多个空白字符的正则表达式是 \s+
# result = ['foo', 'far', 'baz', 'qux']

'''调用 re.split('\s+', text) 时正则表达式会首先被编译,然后正则表达式的 split 方法在
传入文本上被调用。可以使用 re.compile 自行编译,形成一个可复用的正则表达式对象
'''
regex = re.compile('\s+')
result = regex.split(text)			#得到的结果和上面的方法一样

result_all = regex.findall(text)		#返回一个所有匹配正则表达式的模式的列表
# result_all = ['    ', '\t ', '  \t']
  1. 正则表达式方法
方法描述
findall将字符串中所有的非重叠匹配模式以列表形式返回
finditer与 findall 类似,但返回的是迭代器
match在字符串起始位置匹配模式,也可以将模式组建匹配到分组中;如果模式匹配上了,返回一个匹配对象,否则返回 None
search扫描字符串的匹配模式,如果扫描到了返回匹配对象,与 match 方法不同的是,search 方法的匹配可以是字符串的任意位置,而不仅仅是字符串的起始位置
split根据模式,将字符串拆分为多个部分
sub, subn用替换表达式替换字符串中所有的匹配(sub)或第n个出现的匹配串(subn);使用符号 \1, \2, … 来引用替换字符串中的匹配组元素

3.3 pandas 中的向量化字符串函数

部分向量化字符串方法列表

方法描述
cat根据可选的分隔符按元素黏合字符串
contains返回是否含有某个模式/正则表达式的布尔值数组
count模式出现次数的计数
extract使用正则表达式从字符串 Series 中分组抽取一个或多个字符串,返回的结果是每个分组形成一列的 DataFrame
endswith等价于对每个元素使用 x.endswith(模式)
starswith等价于对每个元素使用 x.startswith(模式)
findall找出字符串中所有的模式/正则表达式匹配项,以列表返回
get对每个元素进行索引(获得第 i 个元素)
isalnum等价于内建的 str.alnum
isalpha等价于内建的 str.isalpha
isdecimal等价于内建的 str.isdecimal
isdigit等价于内建的 str.isdigit
isnumeric等价于内建的 str.isnumeric
isupper等价于内建的 str.isupper
join根据传递的分隔符,将Series中的字符串联合
len计算每个字符串的长度
lower, upper转换大小写,等价于对每个元素进行 x.lower() 或 x.upper()
match使用 re.match 将正则表达式应用到每个元素上,将匹配分组以列表形式返回
pad将空白加到字符串左边、右边或两边
center等价于 pad(side=‘both’)
repeat重复值(如 s.str.repeat(3) 等价于对每个字符串进行 *3)
replace以其他字符串替代模式/正则表达式的匹配项
slice对 Series 中的字符串进行切片
split以分隔符或正则表达式对字符串进行拆分
strip对字符串两侧的空白进行消除,包括换行符
rstrip消除字符串右边的空白
lstrip消除字符串左边的空白
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值