文件的读取和写入
文件读取
pandas可以读取很多文件格式。主要有csv,excel,txt文件。
importnumpyasnpimportpandasaspd df_csv=pd.read_csv('a.csv')print(df_csv)# col1 col2 col3 col4 col5#0 2 a 1.4 apple 2020/1/1#1 3 b 3.4 banana 2020/1/2#2 6 c 2.5 orange 2020/1/5#3 5 d 3.2 lemon 2020/1/7importnumpyasnpimportpandasaspd df_txt=pd.read_table('test.txt')print(df_txt)# col1 col2 col3 col4 col5#0 2 a 1.4 apple 2020/1/1#1 3 b 3.4 banana 2020/1/2#2 6 c 2.5 orange 2020/1/5#3 5 d 3.2 lemon 2020/1/7importnumpyasnpimportpandasaspd df_excel=pd.read_excel('my_excel.xlsx')print(df_excel)# col1 col2 col3 col4 col5#0 2 a 1.4 apple 2020-01-01#1 3 b 3.4 banana 2020-01-02#2 6 c 2.5 orange 2020-01-05#3 5 d 3.2 lemon 2020-01-07常用的公共参数,header=None表示第一行不作为列名,index_col表示把某一列或几列作为索引,usecols表示读取列的集合,默认读取所有的列,parse_dates表示需要转化为时间的列,关于时间序列的有关内容将在第十章讲解,nrows表示读取的数据行数。上面这些参数在上述的三个函数里都可以使用。
pd.read_table('test.txt',usecols=['col1','col2'])# col1 col2#0 2 a#1 3 b#2 6 c#3 5 d在读取txt文件时,经常遇到分隔符非空格的情况,read_table有一个分割参数sep,它使得用户可以自定义分割符号,进行txt数据的读取。例如,下面的读取的表以||||为分割:
df_table=pd.read_table('test.txt')# col1||||col2#0 2||||a#1 3||||b#2 6||||c#3 5||||d结果显然不是理想的,这时可以使用sep,同时需要指定引擎为python:
df_table=pd.read_table('test.txt',sep='\|\|\|\|',engine='python')# col1 col2#0 2 a#1 3 b#2 6 c#3 5 d在使用read_table的时候需要注意,参数sep中使用的是正则表达式,因此需要对|进行转义变成\|,否则无法读取到正确的结果。
数据写入
一般在数据写入中,最常用的操作是把index设置为False,特别当索引没有特殊意义的时候,这样的行为能把索引在保存的时候去除。
df_csv.to_csv('a_save.csv',index=False)df_excel.to_excel('my_excel_save.xlsx',index=False)pandas中没有定义to_table函数,但是to_csv可以保存为txt文件,并且允许自定义分隔符,常用制表符\t分割:
df_txt.to_csv('test_save.txt',sep='\t',index=False)如果想要把表格快速转换为markdown和latex语言,可以使用to_markdown和to_latex函数,此处需要安装tabulate包。
df_excel=pd.read_excel('my_excel.xlsx')print(df_excel.to_markdown())#| | col1 | col2 | col3 | col4 | col5 |#|---:|-------:|:-------|-------:|:-------|:--------------------|#| 0 | 2 | a | 1.4 | apple | 2020-01-01 00:00:00 |#| 1 | 3 | b | 3.4 | banana | 2020-01-02 00:00:00 |#| 2 | 6 | c | 2.5 | orange | 2020-01-05 00:00:00 |#| 3 | 5 | d | 3.2 | lemon | 2020-01-07 00:00:00 |print(df_excel.to_latex())#\begin{tabular}{lrlrll}#\toprule&col1&col2&col3&col4&col5 \\#\midrule#0 & 2 & a & 1.400000 & apple & 2020-01-01 00:00:00 \\#1 & 3 & b & 3.400000 & banana & 2020-01-02 00:00:00 \\#2 & 6 & c & 2.500000 & orange & 2020-01-05 00:00:00 \\#3 & 5 & d & 3.200000 & lemon & 2020-01-07 00:00:00 \\#\bottomrule#\end{tabular}基本数据结构
Series
Series一般由四个部分组成,分别是序列的值data、索引index、存储类型dtype、序列的名字name。其中,索引也可以指定它的名字,默认为空。
importpandasaspd s=pd.Series(data=[100,'a',{'dic1':5}],index=pd.Index(['id1',20,'third'],name='my_idx'),dtype='object',name='my_name')print(s)#my_idx#id1 100#20 a#third {'dic1': 5}#Name: my_name, dtype: objectobject代表了一种混合类型,正如上面的例子中存储了整数、字符串以及Python的字典数据结构。此外,目前pandas把纯字符串序列也默认认为是一种object类型的序列,但它也可以用string类型存储。
对于这些属性,可以通过 . 的方式来获取
s.values#array([100,'a',{'dict1':5}],dtype=onj)s.index#Index(['id1','20','third],dtype='object',name='my_idx')s.dtype#dtype('0')s.name#my_nameDataFrame
DataFrame在Series的基础上增加了列索引,一个数据框可以由二维的data与行列索引来构造:
data=[[1,'a',1.2],[2,'b',2.2],[3,'c',3.2]]df=pd.DataFrame(data=data,index=['row_%d'%iforiinrange(3)],columns=['col_0','col_1','col_2'])print(df)# col_0 col_1 col_2#row_0 1 a 1.2#row_1 2 b 2.2#row_2 3 c 3.2更多的时候会采用从列索引名到数据的映射来构造数据框,同时再加上行索引:
df=pd.DataFrame(data={'col_0':[1,2,3],'col_1':list('abc'),'col_2':[1.2,2.2,3.2]},index=['row_%d'%iforiinrange(3)])由于这种映射关系,在DataFrame中可以用[col_name]与[col_list]来取出相应的列与由多个列组成的表,结果分别为Series和DataFrame:
df['col_0']df[['col_0','col_1']]与Series类似,在数据框中同样可以取出相应的属性:
df.values df.columns通过.T可以把DataFrame进行转置:
df.T常用基本函数
汇总函数
head, tail函数分别表示返回表或者序列的前n行和后n行,其中n默认为5info, describe分别返回表的信息概况和表中数值列对应的主要统计量
df.info()df.describe()info, describe只能实现较少信息的展示,如果想要对一份数据集进行全面且有效的观察,特别是在列较多的情况下,推荐使用pandas-profiling包
特征统计函数
在Series和DataFrame上定义了许多统计函数,最常见的是sum, mean, median, var, std, max, min。quantile, count, idxmax这三个函数,它们分别返回的是分位数、非缺失值个数、最大值对应的索引
df_demo.quantile(0.75)df_demo.count()df_demo.idxmax()# idxmin是对应的函数上面这些所有的函数,由于操作后返回的是标量,所以又称为聚合函数,它们有一个公共参数axis,默认为0代表逐列聚合,如果设置为1则表示逐行聚合
唯一值函数
对序列使用unique和nunique可以分别得到其唯一值组成的列表和唯一值的个数
df['School'].unique()#返回出现的内容并去重df['School'].nunique()#返回出现并去重的内容个数value_counts可以得到唯一值和其对应出现的频数
如果想要观察多个列组合的唯一值,可以使用drop_duplicates。其中的关键参数是keep,默认值first表示每个组合保留第一次出现的所在行,last表示保留最后一次出现的所在行,False表示把所有重复组合所在的行剔除。
此外,duplicated和drop_duplicates的功能类似,但前者返回了是否为唯一值的布尔列表,其keep参数与后者一致。其返回的序列,把重复元素设为True,否则为False。drop_duplicates等价于把duplicated为True的对应行剔除。
替换函数
在replace中,可以通过字典构造,或者传入两个列表来进行替换:
df['Gender'].replace({'Female':0,'Male':1}).head()df['Gender'].replace(['Female','Male'],[0,1]).head()另外,replace还有一种特殊的方向替换,指定method参数为ffill则为用前面一个最近的未被替换的值进行替换,bfill则使用后面最近的未被替换的值进行替换。从下面的例子可以看到,它们的结果是不同的
s=pd.Series(['a',1,'b',2,1,1,'a'])#0 a#1 1#2 b#3 2#4 1#5 1#6 a#dtype: objects.replace([1,2],method='ffill')#0 a#1 a#2 b#3 b#4 b#5 b#6 a#dtype: objects.replace([1,2],method='bfill')#0 a#1 b#2 b#3 a#4 a#5 a#6 a#dtype: object逻辑替换包括了where和mask,这两个函数是完全对称的:where函数在传入条件为False的对应行进行替换,而mask在传入条件为True的对应行进行替换,当不指定替换值时,替换为缺失值。
s=pd.Series([-1,1.2345,100,-50])s.where(s<0)#0 -1.0#1 NaN#2 NaN#3 -50.0#dtype: float64s.where(s<0,100)#0 -1.0#1 100.0#2 100.0#3 -50.0#dtype: float64s.mask(s<0)#0 NaN#1 1.2345#2 100.0000#3 NaN#dtype: float64s.mask(s<0,-50)#0 -50.0000#1 1.2345#2 100.0000#3 -50.0000#dtype: float64需要注意的是,传入的条件只需是与被调用的Series索引一致的布尔序列即可。
数值替换包含了round, abs, clip方法,它们分别表示按照给定精度四舍五入、取绝对值和截断。
排序函数
排序共有两种方式,其一为值排序,其二为索引排序,对应的函数是sort_values和sort_index
df_demo=df[['Grade','Name','Height','Weight']].set_index(['Grade','Name'])df_demo.head(3)df_demo.sort_values('Height').head()#对身高进行排序,默认参数ascending=True为升序df_demo.sort_values(['Weight','Height'],ascending=[True,False]).head()#体重相同的情况下,对身高进行排序,并且保持身高降序排列,体重升序排列索引排序的用法和值排序完全一致,只不过元素的值在索引中,此时需要指定索引层的名字或者层号,用参数level表示。另外,需要注意的是字符串的排列顺序由字母顺序决定。
df_demo.sort_index(level=['Grade','Name'],ascending=[True,False]).head()apply()方法
apply方法常用于DataFrame的行迭代或者列迭代,apply的参数往往是一个以序列为输入的函数。例如对于.mean(),使用apply可以如下地写出:
df_demo=df[['Height','Weight']]defmy_mean(x):res=x.mean()returnres df_demo.apply(my_mean)#或者 df_demo.apply(lambda x:x.mean())若指定axis=1,那么每次传入函数的就是行元素组成的Series,其结果与之前的逐行均值结果一致。
窗口对象
pandas中有3类窗口,分别是滑动窗口rolling、扩张窗口expanding以及指数加权窗口ewm。
滑窗对象
要使用滑窗函数,就必须先要对一个序列使用.rolling得到滑窗对象,其最重要的参数为窗口大小window。
importpandasaspd s=pd.Series([1,2,3,4,5])roller=s.rolling(window=3)print(roller)#Rolling [window=3,center=False,axis=0,method=single]在得到了滑窗对象后,能够使用相应的聚合函数进行计算,需要注意的是窗口包含当前行所在的元素,例如在第四个位置进行均值运算时,应当计算(2+3+4)/3,而不是(1+2+3)/3:
print(roller.mean())#计算当前位置包含在内的前3位数的平均,如位置2:(1+2+3)/3,位置3:(2+3+4)/3print(roller.sum())#结算规则同上print(roller.corr(s2))shift, diff, pct_change是一组类滑窗函数,它们的公共参数为periods=n,默认为1,分别表示取向前第n个元素的值、与向前第n个元素做差(与Numpy中不同,后者表示n阶差分)、与向前第n个元素相比计算增长率。这里的n可以为负,表示反方向的类似操作。
s=pd.Series([1,3,6,10,15])print(s.shift(2))print(s.diff(3))将其视作类滑窗函数的原因是,它们的功能可以用窗口大小为n+1的rolling方法等价代替。
扩张窗口
扩张窗口又称累计窗口,可以理解为一个动态长度的窗口,其窗口的大小就是从序列开始处到具体操作的对应位置,其使用的聚合函数会作用于这些逐步扩张的窗口上。具体地说,设序列为a1, a2, a3, a4,则其每个位置对应的窗口即[a1]、[a1, a2]、[a1, a2, a3]、[a1, a2, a3, a4]。
s=pd.Series([1,3,6,10])print(s.expanding().mean())