DataWhale-Pandas-Task2
本文最后更新于 385 天前,其中的信息可能已经有所发展或是发生改变。

二、pandas基础

2.1 文件的读取和写入

2.1.1 文件读取

在pandas中可以读取许多格式的文件,我们主要介绍读取csv,excel,txt文件(需要安装xlrd,xlwt,openpyxl三个包,且xlrd版本不能高于2.0.0)

  • 对于csv文件
df_csv = pd.read_csv('E:/pandas/data/my_csv.csv')
print(df_csv)

显示的结果为:

  • 对于txt文件
df_txt = pd.read_table('E:/pandas/data/my_table.txt')
print(df_txt)

显示结果为:

  • 对于Excel文件
df_excel = pd.read_excel('E:/pandas/data/my_excel.xlsx')
print(df_excel)

显示结果为:

而在文件读取中,我们有一些常用的公共参数,例如:header = None 表示第一行不作为列名;index_col表示把某一列或几列作为索引;usecols表示读取列的集合,默认读取所有的列,parse_dates表示需要转化为时间的列,nrows表示读取的数据行数。这些参数在上述的三个函数里都可以使用。

例:

  • print(pd.read_table('E:/pandas/data/my_table.txt', header=None))

显示结果为:

  • print(pd.read_csv('E:/pandas/data/my_csv.csv', index_col=['col1', 'col2']))

显示结果为:

  • print(pd.read_table('E:/pandas/data/my_table.txt', usecols=['col1', 'col2']))

显示结果为:

  • print(pd.read_csv('E:/pandas/data/my_csv.csv', parse_dates=['col5']))

显示结果为:

  • print(pd.read_excel('E:/pandas/data/my_excel.xlsx', nrows=2))

显示结果为:

我们在读取txt文件时,经常遇到分隔符非空格的情况,read_table有一个分割参数sep,它使得用户可以自定义分割符号,进行txt数据的读取。例如,下面的读取的表以||||为分割:

  • 原本的形式:

print(pd.read_table('E:/pandas/data/my_table_special_sep.txt'))

显示结果为:

上方的结果显然是不理想的,这个时候我们则可以使用sep,同时指定引擎为Python

print(pd.read_table('E:/pandas/data/my_table_special_sep.txt', sep=' |||| ', engine='python'))

显示结果为:

**注意!sep是正则参数,我们需要对|进行转义,只有将其转义为|才能正确读取到结果。`

2.1.2 数据写入

一般在数据的写入中,最常用的操作是将index设置为False,尤其是当索引没有特殊意义的时候,这样的操作可以把索引在保存到时候去除

df_csv.to_csv('E:/pandas/data/my_csv_saved.csv', index=False)
df_excel.to_excel('E:/pandas/data/my_excel_saved.xlsx', index=False)

pandas中没有定义to_table函数,但是to_csv可以保存为txt文件,并且允许自定义分隔符,常用制表符\t分割:

df_txt.to_csv('E:/pandas/data/my_txt_saved.txt', sep='\t', index=False)

而如果我们想要把表格快速转换为markdown或latex语言,我们可以使用to_markdownto_latex函数,此时需要安装tabulate包。

print(df_csv.to_markdown())

print(df_csv.to_latex())

2.2 基本数据结构

2.2.1 Series

Series一般由四个部分组成,分别是序列的值data、索引index、存储类型dtype、序列的名字name。其中,索引也可以指定它的名字,默认为空。

s = pd.Series(data = [100, 'a', {'dic1':5}],
              index = pd.Index(['id1', 20, 'third'], name='my_idx'),
              dtype = 'object',
              name = 'my_name')
print(s)

显示结果如下:

对于其中的属性,我们可以通过.的方式来获取:

print(s.values)

print(s.index)

print(s.dtype)

print(s.name)

print(s.shape)

显示结果如下:

2.2.2 DataFrame

DataFrameSeries的基础上增加了列索引,一个数据框可以由二维的data与行列索引来构造:

data = [[1, 'a', 1.2], [2, 'b', 2.2], [3, 'c', 3.2]]
df = pd.DataFrame(data = data,
                  index = ['row_%d'%i for i in range(3)],
                  columns=['col_0', 'col_1', 'col_2'])
print(df)

显示结果如下:

但一般而言,我们更多的时候会采用从列索引名到数据的映射来构造数据框,同时再加上行索引:

df = pd.DataFrame(data = {'col_0': [1,2,3],
                          'col_1':list('abc'),
                          'col_2': [1.2, 2.2, 3.2]},
                  index = ['row_%d'%i for i in range(3)])
print(df)

显示结果如下:

由于这种映射关系,在DataFrame中可以用[col_name][col_list]来取出相应的列与由多个列组成的表,结果分别为SeriesDataFrame

print(df['col_0'])

print(df[['col_0', 'col_1']])

显示结果如下:

与Series类似,在数据框中同样可以取出相应的属性。

2.3 常用基本函数

为了进行举例说明,在接下来的部分和其余章节都将会使用一份learn_pandas.csv的虚拟数据集,它记录了四所学校学生的体测个人信息。

首先我们查看该数据中的列信息:

df = pd.read_csv('E:/pandas/data/learn_pandas.csv')
print(df.columns)

显示结果如下:

上述列名依次代表学校、年级、姓名、性别、身高、体重、是否为转系生、体测场次、测试时间、1000米成绩,在本章只需使用前七列。

通过df = df[df.columns[:7]]命令提取前七列。

2.3.1 汇总函数

  • head, tail函数分别表示返回表或者序列的前n行和后n行,其中n默认为5:

通过df.head(2)提取前两行的信息,df.tail(3)提取后三行的信息进行数据分析

显示结果为:

  • info, describe分别返回表的信息概况和表中数值列对应的主要统计量:

显示结果为:

【NOTE】
info, describe只能实现较少信息的展示,如果想要对一份数据集进行全面且有效的观察,特别是在列较多的情况下,推荐使用pandas-profiling包.

2.3.2 特征统计函数

SeriesDataFrame上定义了许多统计函数,最常见的是sum, mean, median, var, std, max, min。例如,选出身高和体重列进行演示:

df_demo = df[['Height', 'Weight']]
print(df_demo.mean())
print('-' * 50)
print(df_demo.max())

显示结果为:

此外,我们还需要介绍的是quantile,count,idxmax这三个函数,它们分别返回的是分位数、非缺失值个数、最大值对应的索引:

print(df_demo.quantile(0.75))
print('-' * 50)
print(df_demo.count())
print('-' * 50)
print(df_demo.idxmax()) # idxmin是对应的函数
print('-' * 50)

显示结果为:

上面所有的函数,由于操作后返回的是标量,所以又称为聚合函数,它们有一个公共参数axis,默认为0代表逐列聚合,如果设置为1则表示逐行聚合:

df_demo.mean(axis=1).head() # 在这个数据集上体重和身高的均值并没有意义

2.3.3 唯一值函数

对序列使用uniquenunique可以分别得到其唯一值组成的列表和唯一值的个数:

print(df['School'].unique())
print('-' * 50)
print(df['School'].nunique())
print('-' * 50)

显示结果为:

value_counts可以得到唯一值和其对应出现的频数:

df['School'].value_counts()

显示结果为:

如果想要观察多个列组合的唯一值,可以使用drop_duplicates。其中的关键参数是keep,默认值first表示每个组合保留第一次出现的所在行,last表示保留最后一次出现的所在行,False表示把所有重复组合所在的行剔除。

例:

df_demo = df[['Gender','Transfer','Name']]
df_demo.drop_duplicates(['Gender', 'Transfer'])
print(df_demo.drop_duplicates(['Gender', 'Transfer']))

显示结果为:

此外,duplicateddrop_duplicates的功能类似,但前者返回了是否为唯一值的布尔列表,其keep参数与后者一致。其返回的序列,把重复元素设为True,否则为Falsedrop_duplicates等价于把duplicatedTrue的对应行剔除

print(df_demo.duplicated(['Gender', 'Transfer']).head())
print('-' * 50)

显示结果为:

2.3.4 替换函数

一般而言,替换操作是针对某一个列进行的,因此下面的例子都以Series举例。pandas中的替换函数可以归纳为三类:映射替换、逻辑替换、数值替换。其中映射替换包含replace方法、第八章中的str.replace方法以及第九章中的cat.codes方法,此处介绍replace的用法。

replace中,我们可以通过字典构造,或者传入两个列表来进行替换:

print(df['Gender'].replace({'Female':0, 'Male':1}).head())
print('-' * 50)
print(['Gender'].replace(['Female', 'Male'], [0, 1]).head())
print('-' * 50)

另外,replace还有一种特殊的方向替换,指定method参数为ffill则为用前面一个最近的未被替换的值进行替换,bfill则使用后面最近的未被替换的值进行替换。从下面的例子可以看到,它们的结果是不同的:

s = pd.Series(['a', 1, 'b', 2, 1, 1, 'a'])
print(s.replace([1, 2], method='ffill'))

显示结果为:

print(s.replace([1, 2], method='bfill'))

注意:正则替换请使用str.replace
虽然对于replace而言可以使用正则替换,但是当前版本下对于string类型的正则替换还存在bug,因此如有此需求,请选择str.replace进行替换操作。

接下来我们将了逻辑替换,逻辑替换包括了wheremask,这两个函数是完全对称的:where函数在传入条件为False的对应行进行替换,而mask在传入条件为True的对应行进行替换,当不指定替换值时,替换为缺失值。

s = pd.Series([-1, 1.2345, 100, -50])
print(s.where(s<0))
print('-' * 50)

显示结果为:

需要注意的是,传入的条件只需是与被调用的Series索引一致的布尔序列即可:

s_condition= pd.Series([True,False,False,True],index=s.index)
print(s.mask(s_condition, -50))
print('-' * 50)

显示结果为:

数值替换包含了round, abs, clip方法,它们分别表示按照给定精度四舍五入、取绝对值和截断:

s = pd.Series([-1, 1.2345, 100, -50])
print(s.round(2))
print('-' * 50)
print(s.abs())
print('-' * 50)
print(s.clip(0, 2))# 前两个数分别表示上下截断边界
print('-' * 50)

显示结果为:

2.3.5 排序函数

排序共有两种方式,其一为值排序,其二为索引排序,对应的函数是sort_values和sort_index。

为了演示排序函数,下面先利用set_index方法把年级和姓名两列作为索引:

df_demo = df[['Grade', 'Name', 'Height', 'Weight']].set_index(['Grade','Name'])
print(df_demo.head(3))

显示结果为:

紧接着我们对身高进行排序,默认参数ascending=True为升序:

print(df_demo.sort_values('Height').head())
print('-' * 50)
print(df_demo.sort_values('Height', ascending=False).head())
print('-' * 50)

显示结果为:

在排序中,经常遇到多列排序的问题,比如在体重相同的情况下,对身高进行排序,并且保持身高降序排列,体重升序排列:

df_demo.sort_values(['Weight','Height'],ascending=[True,False]).head()

显示结果为:

索引排序的用法和值排序完全一致,只不过元素的值在索引中,此时需要指定索引层的名字或者层号,用参数level表示。另外,需要注意的是字符串的排列顺序由字母顺序决定。

2.3.6 apply方法

apply方法常用于DataFrame的行迭代或者列迭代,它的axis含义与第2小节中的统计聚合函数一致,apply的参数往往是一个以序列为输入的函数。例如对于.mean(),使用apply可以如下地写出:

df_demo = df[['Height', 'Weight']]
def my_mean(x):
     res = x.mean()
     return res
df_demo.apply(my_mean)

显示结果为:

同样的,可以利用lambda表达式使得书写简洁,这里的x就指代被调用的df_demo表中逐个输入的序列:

df_demo.apply(lambda x:x.mean())

显示结果为:

若指定axis=1,那么每次传入函数的就是行元素组成的Series,其结果与之前的逐行均值结果一致。

df_demo.apply(lambda x:x.mean(), axis=1).head()

显示结果为:

这里再举一个例子:mad函数返回的是一个序列中偏离该序列均值的绝对值大小的均值,例如序列1,3,7,10中,均值为5.25,每一个元素偏离的绝对值为4.25,2.25,1.75,4.75,这个偏离序列的均值为3.25。现在利用apply计算升高和体重的mad指标:

print(df_demo.apply(lambda x:(x-x.mean()).abs().mean()))

显示结果为:

与使用内置的mad函数计算结果一致。

注意:谨慎使用apply
得益于传入自定义函数的处理,apply的自由度很高,但这是以性能为代价的。一般而言,使用pandas的内置函数处理和apply来处理同一个任务,其速度会相差较多,因此只有在确实存在自定义需求的情境下才考虑使用apply。

2.4 窗口对象

【WARNING】谨慎使用apply
得益于传入自定义函数的处理,apply的自由度很高,但这是以性能为代价的。一般而言,使用pandas的内置函数处理和apply来处理同一个任务,其速度会相差较多,因此只有在确实存在自定义需求的情境下才考虑使用apply。

【END】
四、窗口对象
pandas中有3类窗口,分别是滑动窗口rolling、扩张窗口expanding以及指数加权窗口ewm

2.4.1 滑窗对象

要使用滑窗函数,就必须先要对一个序列使用.rolling得到滑窗对象,其最重要的参数为窗口大小window

s = pd.Series([1,2,3,4,5])
roller = s.rolling(window = 3)
roller

显示结果为:

在得到了滑窗对象后,能够使用相应的聚合函数进行计算,需要注意的是窗口包含当前行所在的元素,例如在第四个位置进行均值运算时,应当计算(2+3+4)/3,而不是(1+2+3)/3,此外,还支持使用apply传入自定义函数,其传入值是对应窗口的Series,例如上述的均值函数可以等效表示.

shift, diff, pct_change是一组类滑窗函数,它们的公共参数为periods=n,默认为1,分别表示取向前第n个元素的值、与向前第n个元素做差(与Numpy中不同,后者表示n阶差分)、与向前第n个元素相比计算增长率。这里的n可以为负,表示反方向的类似操作。

2.4.2 扩张窗口

扩张窗口又称累计窗口,可以理解为一个动态长度的窗口,其窗口的大小就是从序列开始处到具体操作的对应位置,其使用的聚合函数会作用于这些逐步扩张的窗口上。具体地说,设序列为a1, a2, a3, a4,则其每个位置对应的窗口即[a1]、[a1, a2]、[a1, a2, a3]、[a1, a2, a3, a4]。

s = pd.Series([1, 3, 6, 10])
s.expanding().mean()

显示结果为:

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇