2020,努力做一个无可替代的人!



作者 | 小一


写在前面的话

本想着三节内容搞定潘大师的前世今生,难搞噢

如果你在读这几篇文章的时候,感觉有些不好理解,一定要和Excel 的操作联系起来

潘大师就是为了解决Excel 处理数据的效率低、重复工作的问题。

要是还觉得不好理解,评论区留言或者加群交流,小一我都在啊。

ok,直接开始开始啦



正文

先想一个问题,在Excel 中,我们常用数据做哪些操作?

小一我觉得应该是透视表,也就是数据分组汇总,不知道你们认不认可

汇总统计

Pandas 的一个主要方法,就是实现数据的汇总统计。

在Pandas 对象中拥有常用的数学和统计方法,一起看看有没有你不知道的

首先创建一个4行3列的DataFrame,并设置行、列索引

# 创建 DataFrame
df_data = pd.DataFrame([[2.1, 3.2, np.nan],
[3.2, np.nan, 1.5],
[2.2, 3.9, 2.2],
[3.2, np.nan, np.nan]
],
index=['one', 'two', 'three', 'four'],
columns=['score1', 'score2', 'score3'])


##### 输出
score1 score2 score3
one 2.1 3.2 NaN
two 3.2 NaN 1.5
three 2.2 3.9 2.2
four 3.2 NaN NaN

通过sum 方法对DataFrame 求和

sum 方法会自动对列进行求和运算

df_data.sum()
# 输出
score1 10.7
score2 7.1
score3 3.7
dtype: float64

NA值会被自动排除,如果整个列都是NaN,则结果也是NaN


如果对存在NA 值的列不进行计算,怎么设置呢?

可以通过参数 skipna 不跳过有NA 值的行或列

df_data.sum(skipna=False)
# 输出
score1 10.7
score2 NaN
score3 NaN
dtype: float64

上面的都是对列进行操作,那行呢?应该怎么设置?

如果对行进行求和运算,将参数axis 设置为1即可,axis默认为0

# 对行进行求和运算
df_data.sum(axis=1)

DataFrame 下axis 参数行用0,列用1


另外,还有一个比较常用的方法:describe

describe 用于一次性产生多个汇总统计

df_data.describe()
# 输出
score1 score2 score3
count 4.000000 2.000000 2.000000
mean 2.675000 3.550000 1.850000
std 0.607591 0.494975 0.494975
min 2.100000 3.200000 1.500000
25% 2.175000 3.375000 1.675000
50% 2.700000 3.550000 1.850000
75% 3.200000 3.725000 2.025000
max 3.200000 3.900000 2.200000

很轻松,describe 直接汇总列的部分统计学指标

还有许多常用的与描述统计相关的方法,我列个表

方法

说明

count

非NA值的数量

describe

针对Series或各DataFrame列计算汇总统计

min、max

计算最小值和最大值

idxmin、idxmax

计算能够获取到最小值和最大值的索引位置

argmin、argmax

计算能够获取到最小值和最大值的索引值

sum、mean、median

值的总和、平均数、算术中位数(50%)

var、std

样本值的方差、标准差

cumsum

样本值的累计和

cummin、cummax

样本值的累计最大值和累计最小值


算术运算

在NumPy 中,我们介绍了广播的概念

​不同维度的数组进行运算会发生广播效应,那么DataFrame中是不是也会发生呢?​

一起来看一下

首先创建两个不同维度的DataFrame 数据

# 创建DataFrame
df_data1 = pd.DataFrame(np.arange(9).reshape(3, 3),
columns=list('abc'),
index=['one', 'two', 'three']
)

# 输出
a b c
one 0 1 2
two 3 4 5
three 6 7 8

# 创建DataFrame
df_data2 = pd.DataFrame(np.arange(16).reshape(4, 4),
columns=list('acde'),
index=['zero', 'one', 'three', 'four']
)
# 输出
a c d e
zero 0 1 2 3
one 4 5 6 7
three 8 9 10 11
four 12 13 14 15

一个是三行三列的DataFrame,一个是四行四列的DataFrame

进行加法运算试试

df_data1+df_data2
# 输出
a b c d e
four NaN NaN NaN NaN NaN
one 4.0 NaN 7.0 NaN NaN
three 14.0 NaN 17.0 NaN NaN
two NaN NaN NaN NaN NaN
zero NaN NaN NaN NaN NaN

有趣的是,运算的时候两个DataFrame 会自动根据行、列对齐

根据行索引、列索引对齐之后,进行相应的运算,没有对齐的位置会置空


没有对齐的数据置空不太好,可以填充其他值吗?

可以的,不过这时候就需要借助函数了

加减乘除分别用 add、sub、div、mul函数

# 没有对齐的位置用 0 填充
df_data1.add(df_data2, fill_value=0)
# 输出
a b c d e
four 12.0 NaN 13.0 14.0 15.0
one 4.0 1.0 7.0 6.0 7.0
three 14.0 7.0 17.0 10.0 11.0
two 3.0 4.0 5.0 NaN NaN
zero 0.0 NaN 1.0 2.0 3.0

没有对齐的位置都已经会被0填充,然后在进行运算

需要注意的是,DataFrame 和Series 之间的运算会产生广播,不过平时不太常用,就不介绍了


唯一值

我们知道,DataFrame可以看做是由许多个Series 组成。

那如果要对DataFrame 某一列检查唯一值的时候,也就是对Series 检查唯一值

唯一值的方法如下:

# 创建Series
series = pd.Series(['a', 'b', 'c', 'a', 'c', 'c', 'b'])
# 唯一值
series.unique()

# 输出
['a' 'b' 'c']


值统计

同样的道理,需要对DataFrame 某一列进行值 统计的时候,也就相当于对Series 进行操作

这次我们直接取DataFrame 的某一列当做Series 对象

# 取DataFrame 某一列
series = df_data['score1']
# 进行值统计
series.value_counts()

# 输出
3.2 2
2.1 1
2.2 1
Name: score1, dtype: int64


函数应用

函数应用这部分是有很大的可拓展性,就和高阶系列的第一节高阶函数一样

​lambda、apply、map、reduce等每一个都是很有用的函数,同时,它们又可以互相结合使用,构造更大的杀伤力。​


稍微介绍一下,大家知道怎么用就行

至于说互相结合使用,后面实战项目中遇到了我们再研究

例如:对DataFrame 列数据进行快速格式化

df_data
# 输出
score1 score2 score3
one 2.1 3.2 NaN
two 3.2 NaN 1.5
three 2.2 3.9 2.2
four 3.2 NaN NaN

# 对score1 列格式化,要求格式:(每一个值-列最小值)/(列最大值-列最小值)
df_data = df_data.apply(lambda x: (x-x.min())/(x.max()-x.min()))
# 输出
score1 score2 score3
one 0.000000 0.0 NaN
two 1.000000 NaN 0.0
three 0.090909 1.0 1.0
four 1.000000 NaN NaN

如果你对数理统计了解的话,应该可以看出来,上面的操作正是对数据进行了离散标准化,使所有的数据落在了【0,1】的区间

正常操作应该是先填充/过滤空值,在进行标准化操作,需注意


索引排序和值排序

根据条件对数据集进行排序是一种很重要的内置运算。

要对行或列索引进行排序,可使用sort_index 方法,它将返回一个已排序的新对象

例如:对Series 进行排序

# 创建Series 
series = pd.Series(range(4), index=['d', 'c', 'a', 'b'])
# 对行索引排序
series.sort_index()

# 输出
a 2
b 3
c 1
d 0
dtype: int64

对于DataFrame,可以根据任意一个轴上的索引进行排序

​通过修改axis 参数设置根据行或列排序,默认为行​

​通过修改ascending 参数设置降序或升序排序,默认为升序​

# 按照列降序排序
df_data.sort_index(axis=1, ascending=False)


对索引排序我清楚了,那能不能对值排序呢?

可以的,同样的我们看一下对Series 和DataFrame 进行值排序

​使用sort_values 方法对Series 按值排序​

series = pd.Series([5, 2, -1, 0])
# 对Series 的值排序
series.sort_values()

# 输出
2 -1
3 0
1 2
0 5
dtype: int64

​使用sort_values 方法对DataFrame 按值进行排序​

区别的是,需要输入要排序的一个或多个行、列标签

# 通过单个列排序
df_data.sort_values(by='score1', axis=0)
# 通过多个列排序
df_data.sort_values(by=['score1', 'score2'], axis=0)

没什么好注意的,按照索引排序和按照值排序,分清楚了就ok了


总结一下:

今天介绍的内容还挺多的,主要有


  • 汇总统计
  • 算术运算
  • 函数应用

其中最主要的还是汇总统计,毕竟是我们处理数据的目的所在。

函数应用可以让我们处理数据更高效,更简单。

当前还有一些DataFrame 的高阶函数,比如map、applymap、groupby等,都是很有用的,将会在后面的实战项目中遇到。



写在后面的话

潘大师系列还有最有一节,等到这两个系列完结之后好好做一个总结

确实有些内容太基础,适合入门看,有的内容又偏难一些,适合已经入门的看

到时候我会好好整理一下再发出来。


碎碎念一下

时间真的可以碎片化到极致,只要你愿意

所以小一最近也在一直努力看书,新买的两本书争取在两个月内看完!


刚才一口气刷了十几道SQL题,时间长不写SQL都有些忘记


群里的每日一题我目前感觉挺好的,新手巩固基础,老手提高技巧,希望大家都能参与进来噢


下节见