温故
在基本数据管理部分,主要是涉及到如何新建数据集,并且对数据集中的变量和观测值进行提取和操作。基本上用到了如下函数,可以根据函数名回忆一下用法:
import pandas as pd
import numpy as np
from pandas import Series, DataFrame
pd.read_table()
# 假设新建一个数据框为df
df.head(), df.tail(), df.shape(), df.dtypes()
df['var'] = values # 新建变量
np.where(), np.logical_and, np.less, np.greater # 变量重编码
df.index, df.columns, df.index.map, df.columns.map, df.index.rename, df.index.reanme # 变量重命名
df.isnull, df.notnull, df.dropna, df,fillna # 缺失值处理
pd.to_datetime# 日期值
df.astype # 数据类型转换
df.sorte_index df.sort.values # 排序
pd.merge, pd.concat, pd.appedn # 合并数据集
df.ix[], df[], df.loc[] # 数据取子集
df.sample # 抽样
知新,一个实际案例
这一次我们使用R语言实战高级数据管理的案例:
要讨论数值和字符处理函数,让我们首先考虑一个数据处理问题。一组学生参加了数学、科学和英语考试。为了给所有学生确定一个单一的成绩衡量指标,需要将这些科目的成绩组合起来。另外,你还想将前20%的学生评定为A,接下来20%的学生评定为B,依次类推。最后,你希望按字母顺序对学生排序。数据如表5-1所示。
观察此数据集,马上可以发现一些明显的障碍。首先,三科考试的成绩是无法比较的。由于它们的均值和标准差相去甚远,所以对它们求平均值是没有意义的。你在组合这些考试成绩之前,必须将其变换为可比较的单元。其次,为了评定等级,你需要一种方法来确定某个学生在前述得分上百分比排名。再次,表示姓名的字段只有一个,这让排序任务复杂化了。为了正确地将其排序,需要将姓和名拆开。

如下介绍的函数大部分在Python自带库如math,内置函数都有,但是都不是元素级别的,也就是必须要写一个显性的循环函数,和numpy,pandas提供的相比效率相差1000倍以上。
数学函数
数学函数主要由numpy提供,避免用到Python的低效的内置循环,转而使用C封装高效的矢量化运算。用法都是np.func()
。
函数 | 描述 |
---|---|
abs, fabs | 绝对值。非复数值,用fabs |
sqrt | 各元素的平方根 |
square | 计算各元素的平方 |
exp | 计算个元素的指数 |
log, log10, log2, log1p | 对数运算 |
sign | 计算各元素的正负号 |
ceil(x) | 不小于x的最小整数 |
floor(x) | 不大于x的最小整数 |
rint(x) | 将x四舍五入到最接近的整数,保留dtype |
cos, sin, tan | 余弦,正弦和正切 |
cosh, sinh, tanh | 双曲余弦,双曲正弦和双曲正切 |
arccos, arcsin, arctan | 反余弦,反正弦和反正切 |
arccosh, arcsinh, arctanh | 反双曲余弦,反双曲正弦和反双曲正切 |
我们经常会用到这些函数对数据进行变换。当然,你可能已经忘记了三角函数对应是什么图形了,这个时候就可以尝试一下自己作图了。
%matplotlib
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
x = np.arange(-2*np.pi, 2*np.pi, 0.01*np.pi)
y = np.cos(x)
plt.plot(x,y)

)
norm.cdf(1.96)
约等于0.975, norm.ppf(0.975)
与等于1.96。
norm.rvs(siez=(4,4))
生成一个4X4的随机数,等同于np.random.normal(size=(4,4))
.
字符处理函数
Python本身的字符处理模块是非常多的,比如说re用于正则,string是常用字符操作模块, 字符串数据类型本身还有许多方法。 我在简书上的一篇文章Python与R的异同(二):字符串操作 就介绍了两则的异同。
这些函数无法直接套用到ndarry, Series, DataFrame数据结构中,需要用到专门的方法。不过,pandas提供了矢量化的字符串方法,更加高效。
方法 | 说明 |
---|---|
len | 计算字符数量 |
contains | 是否符合含指定模式的布尔型数组 |
count | 最大值和最小值的索引位置 |
findall | 计算各字符串的模式列表 |
cat | 实现元素级的字符串连接操作 |
get | 获取第i个元素 |
lower, upper | 大小写转换 |
match | 元素级别的re.match |
split | 根据正则或指定分隔符进行分割 |
strip, rstrip, lstrip | 去除空白符,包括换行符 |
join | 根据指定的分隔符进行连接 |
repeat | 对字符进行重复 |
replace | 用指定的字符串替换找到的模式 |
以《利用Python做数据分析》的数据为例,介绍如何匹配字符,提取指定内容。
data = {'Dava':'dave@google.com','Steve':'steve@gmail.com','Rob':'rob@gmail.com','Wes':np.nan}
data = Series(data)
data.str.contains('gmail')
import re
# 提取姓名等信息
pattern = re.compile(r'([A-Z0-9._%+-]+)@([A-Z0-9.-]+)\.[A-Z]{2,4}', flags=re.IGNORECASE)
data.str.findall(pattern)
将函数应用到Series和DataFrame中
我们介绍的数学函数和统计函数,大部分都是元素级别的操作,也就是能够直接应用到一系列数据结构上,包括Python自带的序列数据结构,list, tuple, numpy的ndarray,pandas提供的Series和DataFrame.
a = 5
np.sqrt(a) # 如果用math.sqrt(5),效率相差100倍
b = np.array([1.243,5.654,2.99])
np.round(b) # 比[round(x) for x in b] 快5倍
c = np.random.uniform(size=(3,4))
np.log(c)
np.mean(c)
默认情况下,np.mean
计算的是总体均值,如果你希望按行按列计算均值的话,可以简单的使用np.meanc(c, axis=1)
,axis的0表示按列,1表示按行。还有一个比较通用的方法类似于R的apply函数。
numpy使用的apply_along_axis
,apply_over_axes
;pandas则是为数据框提供了apply
和applymap
方法. 这里演示pandas的apply
方法, 其他查看帮助文档就行。
# df.apply(func, axis=0), func可以是自定义函数
data = DataFrame(c)
data.apply(np.mean, 1)
除了apply
外,pandas还允许用applymap
映射原来的Python的自带函数成为元素级函数. 比如说直接用math.ceil(data)
是不行的,需要用applymap
进行映射。
data.applymap(lambda x : math.ceil(x)) #相比较np.ceil 效率相差80倍
解决问题
还记得之前提出的问题吗, 先回顾一下,然后用刚才学到的知识进行解决。
将学生的各科考试成绩组合为单一的成绩衡量指标、基于相对名次(前20%,下20%,等等)给出从A到F的评分、根据学生姓氏和名字的首字母对花名册进行排序
第一步: 数据输入
# 导入库
import numpy as np
from pandas import Series, Dataframe
# 数据
roster = pd.read_csv("student_grade.txt", header=None,names=["Student","Math","Science", "English"])
第二步: 计算综合评分。计算综合得分就是先对每一门学科的成绩进行标准化,然后进行相加。标准化的一种方法是归一化,即将一组数据进行均值为0,标准差为1的标准化。
score = np.mean(roster.ix[:,1:].apply(lambda x : (x-np.mean(x))/np.std(x)), axis=1)
roster['score'] = score
这一步比较复杂的就是我用了匿名函数进行标准化,然后用np.mean进行计算均值。
第三步: 计算四分位数, 并且学生进行评分
y = roster.score.quantile(q=[0.8,0.6,0.4,0.2])
grade = np.where(score > y.ix[0.8], 'A', np.where(score > y.ix[0.6], 'B', np.where(score > y.ix[0.4], 'D','F')))
roster['grade'] = grade
这一步用到了np.where进行元素级别的判断。、复制给grade列。
第四步: 根据学生姓氏和名字的首字母对花名册进行排序
first_name = roster.Student.apply(lambda x: x.split(sep=' ')[0])
last_name = roster.Student.apply(lambda x: x.split(sep=' ')[1])
roster['first_name'] = firt_name
roster['last_name'] = last_name
roster.drop('Student', axis=1, inplace=True)
同样用到了匿名函数, 对所有元素应用字符处理函数。
第五步: 排序
roster.sort_values(by=['first_name','last_name'], inplace=True)
最后结果如下:

网友评论