Python:pandas(一)——常用、读写函数read_csv、read_excel、to_csv、to_excel
0、常用
1)读写
①从不同文本文件中读取数据的函数,都是read_xxx的形式;写函数则是to_xxx;
②对前n行感兴趣,或者用于检查读进来的数据的正确性,用head(n)方法;类似的,后n行,用tail(n)——如果不写参数n,将会是5行;信息浏览可以用info()方法;
③检查各列的类型,用dtypes属性。
2)取子集
①这一部分的内容与numpy的切片、索引部分很类似;
②可以通过shape属性查看DataFrame与Series的尺寸;
③如果要查看其中的若干列,索引为这些列名的list,不能单独直接写列名
person_df[['Name','Age']]#列名的list,√
person_df['Name','Age']#直接写列名,×
④筛选特定行,类似numpy中的布尔索引
df[df['Age']>35] | df中Age大于35的行 |
df[func(df['Age'])] | df中对Age进行函数func后返回True的行 |
如果,直接用索引值df['Age']>35,则返回一个与df['Age']相同大小的Series,只是相关的值代之以True或False
3)DataFrame构造
DataFrame是一个2维的数据结构,每行可以存储不同的数据结构。实际上,用Excel表可以更容易理解,每列则表示一个Series(Series是另一种pandas数据结构,一个Series中的数据为同一种类型;此外,Series还有个Name属性),同时有一个列标签;每行也有一个行标签,行标签总是数字0、1、2...。
下面我们显式的构造一个DataFrame,由于一个DataFrame有多个属性列即多个Series。所以构建时先建立一个dict,这个dict的key分别是这些Series的名,value是所有Series在该属性下的value的list,注意顺序一定要一致:
import pandas as pd person={ 'Name':["Braund,Mr.OwenHarris", "Allen,Mr.WilliamHenry", "Bonnell,Miss.Elizabeth",], 'Age':[22,35,58], 'Sex':["male","male","female"], } person_df=pd.DataFrame(person)
#显示出来 person_df Name Age Sex 0 Braund,Mr.OwenHarris 22 male 1 Allen,Mr.WilliamHenry 35 male 2 Bonnell,Miss.Elizabeth 58 female
如果对某列感兴趣,可以通过列名(DataFrame[ 列名 ])的方式直接索引,就像查找dict某个key一样
person_df['Age'] 0 22 1 35 2 58 Name:Age,dtype:int64
关于DataFrame的各项属性及方法,可以看pandas(三);
4)绘图
①直接对整个DataFrame用方法plot,可以得到所有数值列随Index列变化的折线图;
②对某一列用plot,可以得到该列随Index变化的折线图;
③其他的散点图、箱型图,都与matplotlib的相关方法用法相似,而且可以直接从DataFrame的相关方法(见pandas(三))中找到。
④所有plot.*方法的返回值都是Matplotlib对象
5)对列的操作
①对原列的数据进行运算,得到新列的数据,并保存为新列
DataFrame['new'] = DataFrame['old'] * 2
这样就会在最右边生成一个新列'new',其值是'old'列的两倍
②用两列进行运算,结果保存为新列
DataFrame['new'] = DataFrame['old1'] / DataFrame['old2']
③给列重命名
DataFrame_rename = DataFrame.rename( columns={ 'old1':'new1', 'old2':'new2', 'old3':'new3' } )
行列Index均可通过rename重命名,都是dict的格式;
此外,也可以通过传入一个函数,来实现对所有的行列Index进行统一处理,例如:把所以列名的英文小写
DataFrame_rename = DataFrame.rename(columns = str.lower)
6)统计函数
①既可以对整个DataFrame的所有数据列进行统计,也可以只对其中的部分列
对部分列进行统计的用法:
DataFrame[ 列名list ].describe()
air_quality=pandas.read_csv('air_quality_no2.csv') air_quality.describe() station_antwerp station_paris station_london count 95.000000 1004.000000 969.000000 mean 25.778947 27.740538 24.777090 std 12.682019 15.285746 11.214377 min 7.500000 0.000000 0.000000 25% 16.750000 16.500000 19.000000 50% 23.000000 24.150000 25.000000 75% 34.500000 35.925000 31.000000 max 74.500000 97.000000 97.000000
air_quality['station_antwerp'].describe() count 95.000000 mean 25.778947 …… 50% 23.000000 75% 34.500000 max 74.500000 air_quality[['station_antwerp','station_paris']].describe() station_antwerp station_paris count 95.000000 1004.000000 mean 25.778947 27.740538 …… 50% 23.000000 24.150000 75% 34.500000 35.925000 max 74.500000 97.000000
②聚簇统计——先根据某列中的数值分类,再对每类数据进行分类
方法:
DataFrame.groupby(分类依据的列).describe()
DataFrame[ 列名List ].groupby( 分类所依据的列 ).describe() #①列名List中必须包含分类列和需要进行统计的列
#②如果是对整个DataFrame用groupby,则会对除分类列外的所有列进行统计分析
#③分类列可以是多列,此时会分为 这两列类别之积 的类别数
例如:统计不同性别(性别列为'Sex')的年龄数据
DataFrame[ ['Sex','Age'] ].groupby('Sex').describe()
统计每种类别中的数据数量:a.按类别中的样本数量从大到小;b、按类别名从小到大
a.将统计函数变为value_counts()
b.统计函数为count()
titanic["Pclass"].value_counts() Out[12]: 3 491 1 216 2 184 Name: Pclass, dtype: int64 titanic.groupby("Pclass")["Pclass"].count() Out[13]: Pclass 1 216 2 184 3 491 Name: Pclass, dtype: int64
7)重组织DataFrame的表格数据分布(reshape)
①按某列数值大小排序:sort_values(by= 列名 或 列名List)
DataFrame.sort_values(by='Age')
②从长数据到宽数据(单独观察某一列的数据):pivot(见第二部分pandas(二))
8)表格连接
concat(竖向或者横向堆积)与merge(类似数据库的连接)
9)时间数据
将输入的时间文本转化为datetime类型,pd.to_datetime
1、读写函数
正如在0章2节读写部分所说,读函数的格式都是read_xxx,写函数的格式都是to_xxx,不过需要注意的是,read_xxx是pandas的函数,调用方法为pd.read_xxx;to_xxx是DataFrame的方法,用法为DataFrame.to_xxx,相当于直接把某个DataFrame给保存到某个文件中
函数有很多,基本上所有的表格类型数据都可以读进来,有兴趣的可以去pandas官方文档:input/output自己找需要的,下面只介绍read_csv和read_excel
1.1、read_csv
学习自:详解pandas的read_csv方法 - 古明地盆 - 博客园
CSV文件 列与列间的分隔符是逗号,行与行间的分隔符是'\n'
用法
pandas.read_csv( filepath_or_buffer, sep=',', delimiter=None, delim_whitespace=True, header='infer', names=None, index_col=None, usecols=None, mangle_dupe_cols=True, dtype=None, converters=None, true_values=None, false_values=None, skiprows=None, skipfooter=0, nrows=None, low_memory=True, na_values=None, na_filter=True, skip_blank_lines=True, parse_dates=False, infer_datetime_format=False, date_parser=None, iterator=False, compression='infer', encoding=None, error_bad_lines=True, warn_bad_lines=True, )
参数
官方文档中参数多达50个(上文没给全),但也不是每个每次都用得上,下面只说那些自己觉得重要的
参数 | 类型 | 默认值 | 说明 |
filepath_or_buffer | str | 文件名 | |
sep | str | ',' | 分隔符;如果文件列与列间以\t分隔,那么该参数就可以设置为'\t' |
delimiter | str | None | sep的别名 |
delem_whiterspace | bool | True | 分隔符为空白字符,包括空格,\t等 |
header | int或int list | infer |
列索引行。默认第0行; 如果同时给出header和names,则不会默认用第0行而需要手动设置header=0,需要指定header作为索引行;这时会用names作为列名,用除header之外的行作为数据; 如果header=None,则列名就为names,数据为全部 |
names | list | 给列重命名(List大小和全部列数相等,不要误以为和usecols相等) | |
index_col | int | 索引列,如果为None,则会自动生成0,1,2,...的标签列 | |
usecols | list、callable | 列的子集。如果不是每列都用得上,就可以只挑选其中的若干列,可以是列索引的list,比如[0,1,2]表示前3列,也可以是列名的list,比如['name','age'] | |
mangle_dupe_cols | bool | True | 有同名列时,会在重名列名后加.n,n为重名列的序号 |
dtype | {'列名1':type,...} | 指定相关列的类型 | |
converters | {'列名1':func1,...} |
对相关列的值进行转化,举例,如果想让id全部加10,该项可以这样写(由于该参数在使用时默认列类型是string,所以处理数字类型时,需要用类型转换函数) pd.read_csv( 'data.csv', converters={"id":lambdax:int(x)+10} ) |
|
true_values与false_values | list | 哪些值(true_values中说明)被替换为True,哪些值(false_values中说明)被替换为False,只有当某一列的所有数据都在true_values+false_values中时,该列的数据才会被替换为True或False | |
skiprows | int,list |
如果是list,过滤掉哪几行;如果是int,过滤掉前几行 先过滤再确定表头 |
|
skipfooter | int | 0 | 过滤掉最后几行 |
n_rows | int | 读进来多少行(读大文件时有用) | |
low_memory | bool | True |
默认为True,意思是读取数据时,分块读取,可以减小类型错误,但会导致长耗时 设置为False,一次全部读入内存,耗时短,有可能导致内存溢出 |
na_values | str,list | 哪些值被认定为NaN | |
na_filter | bool | True | 缺值是否视为NaN |
skip_blank_lines | bool | True | 是否过滤掉空行,如果False,则将空行视为False |
parse_dates | bool或int list或name list |
如果是True,就把Index列解析为datetime 如果是另外两种:指定某些列为Date类型,配合参数date_parse使用 |
|
infer_datetime_format | bool | False | 如果设置为True且parse_dates存在,则会自动尝试解析这些Date string |
date_parser | function | 解析之前标注的日期列的函数 | |
iterator | bool | False | 如果为True,则返回一个TextFileReader对象,以便逐块处理文件。当文件很大无法一次性读入时,很有用 |
compression | ['infer','gzip','zip',...] | infer | 直接读取压缩文件中的csv文件 |
encoding | 字符集编码类型 | ||
error_bad_lines与warn_bad_lines | bool | True | 删除格式错误的行 |
例子
data = pd.read_csv(csv_name, encoding='GBK', usecols=[1, 5],
names=['Time', 'Changes'],header=0)
由于原CSV文件存在中文,所以读入时encoding='GBK',usecols指明实际读入哪几列,下标从0开始,names为这些列指定index,如果指定了names用作索引,就需要写header=0,表明以第0行为索引行,否则会导致将原来的索引行读入进来当做数据行。
1.2、read_excel
用法
pandas.read_excel( io, sheet_name=0, header=0, names=None, index_col=None,
engine=None, usecols=None, dtype=None, converters=None, true_values=None, false_values=None, skiprows=None, skipfooter=0, nrows=None, na_values=None, keep_default_na=True, na_filter=True, parse_dates=False, date_parser=None, mangle_dupe_cols=True, )
参数
这里只说三个参数io、sheet_name、engine,其他的参数与read_csv相同(但是没有encoding字段),就不再赘述
参数 | 类型 | 默认值 | 说明 |
io | 文件URL,支持xls与xlsx | ||
sheet_name | str,int,list,None | 0 |
str:表的名字 int:表的索引 list:多个表 None:全部表 |
engine | None或"openpyxl" | None |
如果读取的是xlsx文件,需要指定engine为"openpyxl" |
如果设置第二个参数sheet_name=None,就会读入全部的sheet,可以通过data[ sheet_name ]来访问每一个sheet:
data = pd.read_excel( excel_name , sheet_name = None ) data['sheet1'] data['sheet2']
可以通过data.keys()得到所有sheet名:再通过
for sheet in list(data.keys()): ...
data[sheet]访问各sheet,每个sheet都是一个DataFrame
问题:
如果同时用参数usecols和names,会报错Usecols do not match columns,columns expected but not found:[ ... ]
原因:names是给列重命名(List大小和全部列数相等,不要误以为和usecols相等)
解决方法:1、把names参数删去;2、引入names,但是给全部列重命名,并且usecols要和重命名后的列匹配。
1.3、to_csv
用法
DataFrame.to_csv( path_or_buf=None, sep=',', na_rep='', float_format=None, columns=None, header=True, index=True, mode='w', encoding=None, compression='infer', chunksize=None, date_format=None, errors='strict', )
参数
参数 | 类型 | 默认值 | 说明 |
path_of_buf | str | None | 输出文件名 |
sep | 长度为1的str | ',' | 列与列间隔符 |
na_rep | str | '' | 缺省值填充字符串 |
float_format | str | None | 以格式化字符串的形式给出浮点数的形式,类似'%.2f'就是保留两位小数 |
columns | list | 写入哪些列 | |
header | bool,str list | True |
如果是bool,表示是否写入索引行 如果是str list,表示写入时各列的列名(即索引行) |
index | bool | True | 是否写入索引列 |
mode | str | 'w' | python write mode,除了'w'外还有'a'追加 |
encoding | 编码格式 | ||
compression | str | 是否压缩为某种格式 | |
chunksize | int , None | 一次写多少行 | |
date_format | str | None | 格式化字符串的形式给出date类型的形式 |
errors | str | 'strict' | 同open()函数中的errors参数的用法,忽略编码错误用'ignore' |
1.4、to_excel
用法
DataFrame.to_excel( excel_writer, sheet_name='Sheet1', na_rep='', float_format=None, columns=None, header=True, index=True, index_label=None, startrow=0, startcol=0, engine=None, merge_cells=True, encoding=None, inf_rep='inf', verbose=True, freeze_panes=None, storage_options=None )
参数
参数 | 类型 | 默认值 | 说明 |
excel_writer | str、ExcelWrite对象 | 输出文件名 | |
sheet_name | str | 'Sheet1' | 表名 |
na_rep | str | '' | 缺省值的填充 |
float_format | str | 参照该格式将String转化为float数字类型 | |
columns | sequence或str list | 写入的列 | |
header | bool或list of str | True |
是否写入索引行 如果是str list,表示写入时各列的列名(即索引行) |
index | bool | True | 是否写入索引列 |
index_label | str或sequence | 索引列的列名 | |
startrow | int | 0 | 起始行 |
startcol | int | 0 | 起始列 |
merge_cells | bool | True | 将有着多行和多列索引的单元格合并 |
encoding | str | 编码格式,只用于xlwt文件,其他的都是unicode编码 | |
inf_rep | str | 'inf' | 无穷大的填充 |
verbose | bool | True | 日志 |
freeze_panse | 有两个int的tuple | 截止行与列(截止单元格) | |
storge_option | dict |
如果想保存到一个Excel中的多个表中,那么参数excel_writer就不能是单纯的excel文件名,而应该是ExcelWriter对象,就像下边这样:
import pandas as pd excel_writer = pd.ExcelWriter(path, engine='openpyxl') for i in range(30):#生成30个sheet data = pd.DataFrame(...) data.to_excel(excel_writer,f'sheet{i}')#保存为sheet0 sheet1 ... excel_writer.close()
如果以前就有Excel文件和多个表,希望在这些表之后添加新表,可以看:Pandas:to_excel时如何不覆盖之前的Excel表 - ShineLe - 博客园