⛄前言
CSV
(Comma-Separated Values
,逗号分隔值,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)。纯文本意味着该文件是一个字符序列,不含必须像二进制数字那样被解读的数据。CSV
文件由任意数目的记录组成,记录间以某种换行符分隔;每条记录由字段组成,字段间的分隔符是其它字符或字符串,最常见的是逗号或制表符。CSV
文件通常以 .csv
作为文件扩展名。
XLS
就是Microsoft Excel
工作表,是一种非常常用的电子表格格式。xls
文件可以使用Microsoft Excel
打开,另外微软为那些没有安装Excel
的用户开发了专门的查看器Excel Viewer
。使用Microsoft Excel
可以将XLS
格式的表格转换为多种格式:XML
表格、XML
数据、网页、使用制表符分割的文本文件(.txt
)、使用逗号分隔的文本文件(.csv
)等。
XLSX
是Microsoft Office EXCEL 2007/.../2019
文档及以上的扩展名。其基于Office Open XML
标准的压缩文件格式取代以前专有的默认文件格式,在传统文件名扩展名后面添加字母"x
"(即.docx
取代.doc
、.xlsx
取代.xls
、.pptx
取代.ppt
)。任何能够打开.xlsx
文件的文字处理软件都可以将该文档转换为.xls
文件,.xlsx
文件比.xls
文件所占用空间更小。
xlsx
格式文档文件无法被EXCEL2003
及以下版本EXCEL
软件直接打开编辑,安装OFFICE2007
兼容包后可以打开查看。手动将XLSX
文件后缀修改为XLS
无法改变文档文件的本质属性,是不能被EXCEL2003
等低版本EXCEL
直接打开编辑的。用户可在EXCEL
软件成功打开EXCEL2007
专有XLSX
格式文档的前提下,采用另存为方式将其转换为EXCEL97—2003
格式文档的XLS
文件这样可与旧的版本兼容,但一些EXCEL2007
文档专有的特性格式可能丢失。Excel xls
和xlsx
的详细区别如下:
- 文件格式不同:
xls
是一个特有的二进制格式,其核心结构是复合文档类型的结构,而xlsx
的核心结构是XML
类型的结构,采用的是基于XML
的压缩方式,使其占用的空间更小。xlsx
中最后一个x
的意义就在于此。- 版本不同:
xls
是excel2003
及以前版本生成的文件格式,不管有没有宏程序的话都是xls
文件,而xlsx
是excel2007
及以后版本生成的文件格式,从2007
开始做了区分,XLSM
文件和XLSX
文件都是excel2007
及其以后的文件,但前者是含有宏启用,Excel
中默认情况下不自动启用宏,默认是XLSX
。VBA
中,如果不想保存代码,可以保存为xlsx
,即可自动删除其中VBA
代码,反之则保存为XLSM
文件。- 兼容性不同:
xlsx
格式是向下兼容的,可兼容xls
格式。07版的Office Excel
,能打开编辑07版(后缀.xlsx
)的Excel
文件,也能打开编辑03版(后缀.xls
)的Excel
文件,都不会出现乱码或者卡死的情况。03版的Office Excel
,就只能打开编辑03版(后缀.xls
)的Excel
文件;如果打开编辑07版(后缀.xlsx
)的Excel
文件,则可能出现乱码或者开始能操作到最后就卡死,以后一打开就卡死。- 默认保存方式上:
xls
是03版Microsoft Office Excel
工作表的格式,用03版Office,新建Excel
默认保存的Excel
文件格式的后缀是.xls
;xlsx
是07版Microsoft Office Excel
工作表的格式,用07版Office,新建Excel
默认保存的的Excel
文件格式后缀是.xlsx
。- 容量不同:
xls
只有65536行、256列;xlsx
可以有1048576行、16384列
JSON
(JavaScript Object Notation
, JS
对象简谱)是一种轻量级的数据交换格式。它基于 ECMAScript(欧洲计算机协会制定的js
规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得JSON
成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
XML
(Extensible Markup Language
, 可扩展标记语言) ,标准通用标记语言的子集,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。 XML
是标准通用标记语言可扩展性良好,内容与形式分离,遵循严格的语法要求,保值性良好等优点。
TXT
文件是微软在操作系统上附带的一种文本格式,是最常见的一种文件格式,早在DOS时代应用就很多,主要存储文本信息,即为文字信息,现在的操作系统大多使用记事本等程序保存,大多数软件可以查看,如记事本,浏览器等等。
⛄Python之读写文件
👀CSV
(1)CSV库读取
csv.reader
:以列表的形式返回读取的数据;
csv.writer
:以列表的形式写入数据;
csv.DictReader
:以字典的形式返回读取的数据;
csv.DictWriter
:以字典的形式写入数据。
import csv
with open(r"D:\Desktop\data.csv") as file:
reader = csv.reader(file)
print(reader)
print("*"*20)
# 用next()函数读取文件时:如果只执行一次默认读取第一行。
headers = next(reader)
print(headers)
print("*"*20)
for row in reader:
print(row)
print(row[2])
# 输出结果
<_csv.reader object at 0x000001D6B95F1668>
********************
['name', 'gender', 'age', 'hobby']
********************
['小红', '女', '20', '跑步']
20
['小汤', '男', '22', '篮球']
22
['小李', '男', '24', '足球']
24
namedtuple
(具名元组),因为元组的局限性:不能为元组内部的数据进行命名,所以往往我们并不知道一个元组所要表达的意义,在这里引入了collections.namedtuple
这个工厂函数,来构造一个带字段名的元组。具名元组的实例和普通元组消耗的内存一样多,因为字段名都被存在对应的类里面。
# 获取一行数据中的某一列数据
import csv
from collections import namedtuple
with open(r"D:\Desktop\data.csv") as file:
reader = csv.reader(file)
print(reader)
print("*"*20)
headers = next(reader)
# namedtuple(具名元组)返回一个具名元组子类 typename
Row = namedtuple('Row', headers)
print(headers)
print("*"*20)
for row in reader:
# 列表或元组前面加星号作用是将列表解开成两个独立的参数;
# 字典前面加两个星号,是将字典的值解开成独立的元素作为形参。
row = Row(*row)
# 获取一行数据中的某一列数据。
print(row.name,row.age)
# 输出结果
<_csv.reader object at 0x000001D6B95F1128>
********************
['name', 'gender', 'age', 'hobby']
********************
小红 20
小汤 22
小李 24
简单使用csv.DictReader
可以深入了解该函数的参数:
csv.DictReader()
之fieldnames
参数csv.DictReader()
之restkey
参数csv.DictReader()
之restval
参数
import csv
with open(r"D:\Desktop\data.csv") as file:
'''
# 如果没有字段名,参数fieldnames
reader = csv.DictReader(file,fieldnames = ['name','gender','age','hobby'])
# next()方法用于移动指针
head_row = next(reader)
'''
reader = csv.DictReader(file)
print(reader)
print("*"*20)
for row in reader:
# OrderedDict是一种长相类似于列表的数据类型,该列表中嵌套着元组;
# 每个元组中的第一个元素为键,第二个元素为值(类似于字典)
print(row)
print(row["name"],row["hobby"])
# 输出结果
<csv.DictReader object at 0x000001D6B95F0388>
********************
OrderedDict([('name', '小红'), ('gender', '女'), ('age', '20'), ('hobby', '跑步')])
小红 跑步
OrderedDict([('name', '小汤'), ('gender', '男'), ('age', '22'), ('hobby', '篮球')])
小汤 篮球
OrderedDict([('name', '小李'), ('gender', '男'), ('age', '24'), ('hobby', '足球')])
小李 足球
(2)CSV库写入
csv.reader
:以列表的形式返回读取的数据;
csv.writer
:以列表的形式写入数据;
csv.DictReader
:以字典的形式返回读取的数据;
csv.DictWriter
:以字典的形式写入数据。
import csv
# 1. 创建文件对象(指定文件名,模式,编码方式),指定下次写入在这次的下一行
# 注意引入newline="",不然加入的数据会空一行
with open(r"D:\Desktop\data.csv", "a+", encoding="gbk", newline="") as f:
# 2. 基于文件对象构建 csv写入对象
csv_writer = csv.writer(f)
# 3. 构建列表头
# name = ['name','gender','age','hobby']
# csv_writer.writerow(name)
# 4. 写入csv文件内容
z = [["小ai", "男", 21, "篮球"],["小张", "男", 25, "篮球"]]
csv_writer.writerows(z)
with open(r"D:\Desktop\data.csv", "r+", encoding="gbk", newline="") as f:
reader = csv.reader(f)
headers = next(reader)
for row in reader:
print(row)
# 输出结果
['小红', '女', '20', '跑步']
['小汤', '男', '22', '篮球']
['小李', '男', '24', '足球']
['小ai', '男', '21', '篮球']
['小张', '男', '25', '篮球']
如果
csvfile
是文件对象,则打开它时应使用newline=""
。如果没有指定newline=""
,则嵌入引号中的换行符将无法正确解析,并且在写入时,使用\r\n
换行的平台会有多余的\r
写入。由于csv
模块会执行自己的(通用)换行符处理,因此指定newline=""
应该总是安全的。
open()
完成后必须调用close()
方法关闭文件,因为文件对象会占用操作系统资源,并且操作系统同一时间能打开的文件数量也是有限的。由于文件读写时有可能产生IOError
,一旦出错,后面的f.close()
就不会调用。with open()
则可以避免这样的情况。
模式 | 描述 |
---|---|
t | 以文本格式打开文件(默认)。一般用于文本文件,如:txt 。 |
b | 以二进制格式打开文件。一般用于非文本文件,如:图片。 |
r | 以只读方式打开文件(默认模式)。文件的指针将会放在文件的开头,如果文件不存在会报错。 |
w | 以只写方式打开文件。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,则创建新文件。 |
a | 以追加方式打开文件,同样是只写,不允许进行读操作。如果文件已存在,文件指针将会放在文件的结尾,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
r+ | 打开一个文件用于读写。如果文件存在,则打开文件,将文件指针定位在文件头,新写入的内容在原有内容的前面;如果文件不存在会报错。 |
w+ | 打开一个文件用于读写。如果文件存在,则打开文件,清空原有内容,进入编辑模式;如果文件不存在,则创建一个新文件进行读写操作。 |
a+ | 以追加模式打开一个文件用于读写。如果文件存在,则打开文件,将文件指针定位在文件尾,新写入的内容在原有内容的后面;如果文件不存在,则创建一个新文件用于读写。 |
rb | 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。一般用于非文本文件如图片等。 |
wb | 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。 |
ab | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
rb+ | 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。一般用于非文本文件如图片等。 |
wb+ | 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。 |
ab+ | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。 |
csv
库常见的问题
csv.DictWriter()
:该函数返回的结果遍历一次之后,再次遍历返回的结果是空列表。csv.reader()
:返回的结果是结构体,需要for
循环才能调用,不能像list
那样直接选取特定单元格。- 通过列名来查找指定列的操作麻烦。
(3)pandas库读取
使用
pandas
读取csv
文件的优势:
- 方便,有专门支持读取
csv
文件的pd.read_csv()
函数;- 将
csv
转换成二维列表形式;- 支持通过列名查找特定列;
- 相比
csv
库,事半功倍。
pandas.read_csv(filepath_or_buffer, sep=, delimiter=None, header=‘infer’, names=None, index_col=None, usecols=None, squeeze=False, prefix=None, mangle_dupe_cols=True, dtype=None, engine=None, converters=None, true_values=None, false_values=None, skipinitialspace=False, skiprows=None, skipfooter=0, nrows=None, na_values=None, keep_default_na=True, na_filter=True, verbose=False, skip_blank_lines=True, parse_dates=False, infer_datetime_format=False, keep_date_col=False, date_parser=None, dayfirst=False, cache_dates=True, iterator=False, chunksize=None, compression=‘infer’, thousands=None, decimal=’.’, lineterminator=None, quotechar='"', quoting=0, doublequote=True, escapechar=None, comment=None, encoding=None, dialect=None, error_bad_lines=True, warn_bad_lines=True, delim_whitespace=False, low_memory=True, memory_map=False, float_precision=None, storage_options=None)
# 常用参数详解
(1)filepath_or_buffer:必须有的参数,其它都是按需求选用的。文件所在处的路径。
(2)sep:指定分隔符,默认为逗号','。
(3)delimiter:str/default/None,定界符,备选分隔符(如果指定该参数,则sep参数失效)
(4)header:int or list of ints, default ‘infer’,指定哪一行作为表头。默认设置为0(即第一行作为表头),如果没有表头的话,要修改参数,设置header=None。
(5)names:指定列的名称,用列表表示。一般我们没有表头,即header=None时,这个用来添加列名就很有用啦。
(6)index_col:指定哪一列数据作为行索引,可以是一列,也可以多列。多列的话,会看到一个分层索引。
(7)squeeze:布尔值,默认为False。如果解析的数据仅包含一列,则返回一个Series。
(8)prefix:给列名添加前缀。如prefix="x",会出来"x1"、"x2"、"x3"。
(9)nrows:int, default None。需要读取的行数(从文件头开始算起)。
(10)encoding:编码方式。
(11)skiprows:list-like or integer, default None。在文件开始处要跳过的行号(索引为0)或要跳过的行数(整数)。
......
import pandas as pd
df = pd.read_csv(r"D:\Desktop\data.csv",encoding="gbk")
print(df)
print("*"*20)
print(df.index.values)
print(df.columns.values)
print(df.values)
# 通过位置选取
print("="*20)
print(df.iloc[:,0:3].values)
print(type(df.iloc[:,0:3].values))
print(df.iloc[:,0:3].values.tolist())
print(type(df.iloc[:,0:3].values.tolist()))
# 通过标签选取
print("-"*20)
print(df.loc[[0,3],["name","hobby"]].values)
# 输出结果
name gender age hobby
0 小红 女 20 跑步
1 小汤 男 22 篮球
2 小李 男 24 足球
3 小ai 男 21 篮球
4 小张 男 25 篮球
********************
[0 1 2 3 4]
['name' 'gender' 'age' 'hobby']
[['小红' '女' 20 '跑步']
['小汤' '男' 22 '篮球']
['小李' '男' 24 '足球']
['小ai' '男' 21 '篮球']
['小张' '男' 25 '篮球']]
====================
[['小红' '女' 20]
['小汤' '男' 22]
['小李' '男' 24]
['小ai' '男' 21]
['小张' '男' 25]]
<class 'numpy.ndarray'>
[['小红', '女', 20], ['小汤', '男', 22], ['小李', '男', 24], ['小ai', '男', 21], ['小张', '男', 25]]
<class 'list'>
--------------------
[['小红' '跑步']
['小ai' '篮球']]
(4)pandas库写入
DataFrame.to_csv(path_or_buf=None, sep=',', na_rep='', float_format=None, columns=None, header=True, index=True, index_label=None, mode='w', encoding=None, compression='infer', quoting=None, quotechar='"', lineterminator=None, chunksize=None, date_format=None, doublequote=True, escapechar=None, decimal='.', errors='strict', storage_options=None)
# 常用参数详解
(1)path_or_buf:字符串,放文件名、相对路径、文件流等。
(2)sep:字符串,分隔符,跟read_csv()的一个意思。
(3)na_rep:字符串,将NaN转换为特定值。
(4)columns:列表,指定哪些列写进去。
(5)header:默认header=0,如果没有表头,设置header=None,表示我没有表头呀!
(6)index:关于索引的,默认True,写入索引
(7)mode:{‘w’, ‘x’, ‘a’}, default ‘w’,写入方式。
(8)encoding:编码方式。
......
import pandas as pd
name = ["小小","小耿"]
gender = ["男","男"]
age = [20,25]
hobby = ["跳绳","羽毛球"]
dict_data = {"name":name,"gender":gender,"age":age,"hobby":hobby}
df1 = pd.DataFrame(dict_data)
# mode = "a"为追加数据,index为每行的索引序号,header为标题
df1.to_csv("D:\Desktop\data.csv",mode="a",index=False,header=False,encoding="gbk")
df2 = pd.read_csv(r"D:\Desktop\data.csv",encoding="gbk")
print(df2)
# 输出结果
name gender age hobby
0 小红 女 20 跑步
1 小汤 男 22 篮球
2 小李 男 24 足球
3 小ai 男 21 篮球
4 小张 男 25 篮球
5 小小 男 20 跳绳
6 小耿 男 25 羽毛球
👀Excel
python
用于读写excel
文件的库有很多,除了前面提到的pandas
,还有xlrd
、xlwt
、openpyxl
、xlwings
等等。这里以pandas
库为例对Excel
进行操作。
xlrd
库:从excel
中读取数据,支持xls
、xlsx
;xlwt
库:对excel
进行修改操作,不支持对xlsx
格式的修改;xlutils
库:在xlw
和xlrd
中,对一个已存在的文件进行修改;openpyxl
库:主要针对xlsx
格式的excel
进行读取和编辑;xlwings
库:对xlsx
、xls
、xlsm
格式文件进行读写、格式修改等操作;xlsxwriter
库:用来生成excel
表格,插入数据、插入图标等表格操作,不支持读取;Microsoft Excel API
:需安装pywin32
,直接与Excel
进程通信,可以做任何在Excel
里可以做的事情,但比较慢。
(1)读取Excel文件
read_excel()
读取xlsx
文件:
pd.read_excel(io, sheet_name=0, header=0, names=None, index_col=None, usecols=None, squeeze=False,dtype=None, engine=None, converters=None, true_values=None, false_values=None, skiprows=None, nrows=None, na_values=None, parse_dates=False, date_parser=None, thousands=None, comment=None, skipfooter=0, convert_float=True, **kwds)
# 常见参数详解
(1)io:文件的路径。
(2)sheet_name:读取的工作表的名称;可以是整型数字、列表名,如果读取多个sheet,也可以是它们组成的列表;以0为起始点。
(3)header:指定哪几行做列名;默认header为0,如果设置为[0,1],则表示将前两行作为多重索引。
(4)names:自定义列名;长度必须和excel的列大小相同;如果缺少列名,使用names指定列名字,会替代原来的列表头。
(5)index_col:用作索引的列;可以是某列的名字,也可以是整型数字或列表。
(6)usecols:指定读取的列;列从0开始,可以是列表,也可以使用Excel的列名,如'A','B'等字母。
(7)squeeze:一列数据时,返回Series还是DataFrame。仅当Excel只有一列的时候起作用,squeeze为True时,返回Series,反之返回DataFrame。
(8)skiprows:跳过指定行;skiprows=n,跳过前n行;skiprows=[a,b,c],跳过第a+1,b+1,c+1行(索引从0开始);使用skiprows后,可能会跳过行首,也就是列名。
(9)nrows:需要读取的行数,表示只读取excel的前nrows行,包括表头。
(10)skipfooter:跳过末尾n行。
......
import pandas as pd
# 读取xlsx,设置sheet位置,详细参数解释可以检索该函数
data = pd.read_excel(r"D:\Desktop\data.xlsx",sheet_name=0)
print(data)
print(type(data))
print("*"*20)
print(data.iloc[:,[0,1,3]].values)
print(data.iloc[:,[0,1,3]].values.tolist())
# 输出结果
name gender age hobby
0 小红 女 20 跑步
1 小汤 男 22 篮球
2 小李 男 24 足球
3 小ai 男 21 篮球
4 小张 男 25 篮球
5 小小 男 20 跳绳
6 小耿 男 25 羽毛球
<class 'pandas.core.frame.DataFrame'>
********************
[['小红' '女' '跑步']
['小汤' '男' '篮球']
['小李' '男' '足球']
['小ai' '男' '篮球']
['小张' '男' '篮球']
['小小' '男' '跳绳']
['小耿' '男' '羽毛球']]
[['小红', '女', '跑步'], ['小汤', '男', '篮球'], ['小李', '男', '足球'], ['小ai', '男', '篮球'], ['小张', '男', '篮球'], ['小小', '男', '跳绳'], ['小耿', '男', '羽毛球']]
(2)写入Excel文件
to.excel()
保存xlsx
文件:
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)
# 参数详解
(1)excel_writer:字符串或ExcelWriter对象;文件路径或现有的ExcelWriter。
(2)sheet_name:字符串,默认"Sheet1"将包含DataFrame的表的名称。
(3)na_rep:字符串,默认''缺失数据表示方式。
(4)float_format:字符串,默认None格式化浮点数的字符串。
(5)columns:序列,可选要编写的列。
(6)header:布尔或字符串列表,默认为Ture。写出列名。如果给定字符串列表,则假定它是列名称的别名。
(7)index:布尔,默认的Ture写行名(索引)。
......
ExcelWriter()
可以向同一个excel
的不同sheet
中写入对应的表格数据,首先需要实例化一个writer
对象,传入的主要参数为已存在容器表格的路径及文件名称。
# 用于将DataFrame对象写入Excel工作表的类。默认值是对xls使用xlwt,对xlsx使用openpyxl。
class pandas.ExcelWriter(path, engine=None, date_format=None, datetime_format=None, mode='w', **engine_kwargs)
# 参数详解
(1)path:str,xls或xlsx文件的路径。
(2)engine:str (可选参数),用于编写的引擎,常见的引擎有"openpyxl"和"xlsxwriter"。如果为无,则默认为xlsxwriter,但是"xlsxwriter"模块不支持追加操作,需要追加新的sheet操作选择"openpyxl"参数,否则会报错。注意:只能作为关键字参数传递。
(3)date_format:str,默认为None,格式字符串,用于写入Excel文件的日期(例如"YYYY-MM-DD")。
(4)datetime_format:str,默认为None,写入Excel文件的日期时间对象的格式字符串。(例如"YYYY-MM-DD HH:MM:SS")。
(5)mode:{"w","a"},默认为"w",要使用的文件模式(写或追加)。
(6)if_sheet_exists:{'error','new','replace','overlay'},默认'error',写入的sheet name已存在时代码操作。默认'error'表示报错;'new'表示engine自动创建新的其他sheet name;'replace'表示覆盖原sheet数据,在写入之前删除工作表的内容;'overlay'表示将内容写入现有工作表而不删除旧内容。
为了与CSV编写器兼容,ExcelWriter在写入之前将列表和字典序列化为字符串。
在使用
pd.ExcelWriter()
的时候可能会出现问题:if_sheet_exists=‘overlay’ 不起作用查阅资料:
if_sheet_exists{'error', 'new', 'replace', 'overlay'}
,如果pandas
的版本过低,是没有overlay
参数的,需要升级pandas
版本。我的版本:pandas-2.0.1
# 追加数据
import pandas as pd
name = ["小伟","小猪"]
gender = ["男","男"]
age = [20,18]
hobby = ["跳绳","台球"]
dict_data = {"name":name,"gender":gender,"age":age,"hobby":hobby}
df = pd.DataFrame(dict_data)
with pd.ExcelWriter(r"D:\Desktop\data.xlsx", engine='openpyxl', mode='a',if_sheet_exists='overlay') as writer:
df1 = pd.DataFrame(pd.read_excel(r"D:\Desktop\data.xlsx", sheet_name='data'))
df_rows = df1.shape[0] #获取原数据的行数
# 将数据df写入excel中的sheet1表,从第一个空行开始写
# 为了避免覆盖现有内容,要告诉to_excel方法从新的一行开始写,参数startrow设为"原行数+1"
df.to_excel(writer, sheet_name='data',startrow=df_rows+1, index=False, header=False)
df2 = pd.read_excel(r"D:\Desktop\data.xlsx",sheet_name=0)
print(df2)
# 输出结果
name gender age hobby
0 小红 女 20 跑步
1 小汤 男 22 篮球
2 小李 男 24 足球
3 小ai 男 21 篮球
4 小张 男 25 篮球
5 小小 男 20 跳绳
6 小耿 男 25 羽毛球
7 小伟 男 20 跳绳
8 小猪 男 18 台球
写入Excel
的几种情形与方式(覆盖、新增、追加、对齐),具体细节见:参考博客①、参考博客②
import pandas as pd
import numpy as np
s1 = pd.DataFrame(np.array([['s1', 's1', 's1', 's1']]), columns=['a', 'b', 'c', 'd'])
s2 = pd.DataFrame(np.array([['s2', 's2', 's2', 's2']]), columns=['a', 'b', 'c', 'd'])
# (1)删除文件原有数据,只保留s2一份数据(最后一份)
# s1.to_excel(r"D:\Desktop\test.xlsx", sheet_name="111", index=False)
# s2.to_excel(r"D:\Desktop\test.xlsx", sheet_name="222", index=False)
with pd.ExcelWriter(r"D:\Desktop\test2.xlsx") as writer:
# (2) 删除文件原有数据,同时保留s1和s2两份数据
s1.to_excel(writer, sheet_name="111", index=False)
s2.to_excel(writer, sheet_name="222", index=False)
👀JSON
常见的处理JSON
文件的第三方库(速度不同)包括:json
、simplejson
、ujson
、orjson
、simdjson
、rapidjson
。一般情况下的json
文件,存储的是python
中的一个dict
。这里以map.geojson
文件和CPython 本身的json
模块为例,源文件内容如下。参考博客①、参考博客②
{
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {},
"geometry": {
"coordinates": [[[116.3591064789793, 40.0611769097348], [116.35882714532096, 40.06035824493355], [116.3588680234169, 40.06017052423036], [116.3592154872361, 40.05968557668524], [116.35964470724883, 40.05949263960517], [116.36125939205749, 40.05968557668524], [116.36073478982053, 40.06143241456951], [116.3591064789793, 40.0611769097348]]],
"type": "Polygon"
}
}, {
"type": "Feature",
"properties": {},
"geometry": {
"coordinates": [116.35838429946176, 40.0595499993847],
"type": "Point"
}
}, {
"type": "Feature",
"properties": {},
"geometry": {
"coordinates": [116.36078873507478, 40.06152377992771],
"type": "Point"
}
}
]
}
使用JSON
函数需要导入json
库:import json
函数 | 描述 |
---|---|
json.loads() | 将已编码的JSON 字符串解码为Python 对象 |
json.dumps() | 将Python 对象编码成JSON 字符串 |
json.loads(s, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
# 参数详解
(1)s:要解码的JSON字符串。
(2)cls:指定用于解码JSON字符串的自定义类。
(3)object_hook:指定一个回调函数,将解码后的JSON对象转换成其他Python对象。
(4)parse_float:指定一个回调函数,将解码后的JSON浮点数转换成Python浮点数。
(5)parse_int:指定一个回调函数,将解码后的JSON整数转换成Python整数。
(6)parse_constant:指定一个回调函数,用于解析JSON中的常量(例如null,true,false)。
(7)object_pairs_hook:指定一个回调函数,将解码后的JSON对象返回为Python的键值对。
json.dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)
# 参数详解
(1)obj:转化成json的对象。
(2)skipkeys:是否跳过无法被JSON序列化的key(包括str, int, float, bool, None)。
(3)ensure_ascii:输出保证将所有输入的非ASCII字符转义。
(4)check_circular:是否检查循环引用。
(5)allow_nan:是否允许JSON规范外的float数据(nan, inf, -inf)。
(6)indent:是一个正整数, 代表序列化后的缩进。
(7)separators:是一个格式为 (item_separator, key_separator) 的元组, 默认取值为 (',',':')。
(8)default:是一个函数, 当某个value无法被序列化时, 对其调用该函数。
(9)sort_keys:是否对数据按照key进行排序。
# 读取json
import json
with open(r"D:\Desktop\map.geojson", 'r') as f:
content = f.read()
a = json.loads(content)
print(type(a))
print(a)
print("*"*20)
print(a["features"][2]["geometry"])
# 输出结果
<class 'dict'>
{'type': 'FeatureCollection', 'features': [{'type': 'Feature', 'properties': {}, 'geometry': {'coordinates': [[[116.3591064789793, 40.0611769097348], [116.35882714532096, 40.06035824493355], [116.3588680234169, 40.06017052423036], [116.3592154872361, 40.05968557668524], [116.35964470724883, 40.05949263960517], [116.36125939205749, 40.05968557668524], [116.36073478982053, 40.06143241456951], [116.3591064789793, 40.0611769097348]]], 'type': 'Polygon'}}, {'type': 'Feature', 'properties': {}, 'geometry': {'coordinates': [116.35838429946176, 40.0595499993847], 'type': 'Point'}}, {'type': 'Feature', 'properties': {}, 'geometry': {'coordinates': [116.36078873507478, 40.06152377992771], 'type': 'Point'}}]}
********************
{'coordinates': [116.36078873507478, 40.06152377992771], 'type': 'Point'}
# 将字典保存成json
import json
a = {
"type": "Feature",
"properties": {},
"geometry": {
"coordinates": [116.36078873507478, 40.06152377992771],
"type": "Point"
}
}
b_str = json.dumps(a)
print(type(b_str))
with open(r"D:\Desktop\new_json.json", 'w') as f:
f.write(b_str)
with open(r"D:\Desktop\new_json.json", 'r') as f:
content = f.read()
a = json.loads(content)
print(a)
# 输出结果
<class 'str'>
{'type': 'Feature', 'properties': {}, 'geometry': {'coordinates': [116.36078873507478, 40.06152377992771], 'type': 'Point'}}
👀XML
在Python
中,有多个库可以用来读取和处理XML
文档。以下是其中一些常用的库:
xml.etree.ElementTree(
内置库):这是Python
标准库中的一个模块,提供了基本的XML
文档解析和操作功能。它具有简单的API和高效的性能,适合处理小型到中型的XML
文档。lxml
:lxml
是Python
中一个功能强大的XML/HTML
解析库,基于libxml2
和libxslt
库。它提供了与ElementTree
相似的API
,但具有更好的性能和更多的功能。lxml
支持XPath
、XSLT
、XML Schema
等高级特性,适用于处理大型和复杂的XML
文档。xmltodict
:xmltodict
库可以将XML
文档解析为Python
字典,使XML
数据的处理更加简便。它提供了一个简单的API
,将XML
数据转换为Python
数据结构,便于数据的操作和处理。minidom
:xml.dom.minidom
是Python
标准库中的一个模块,提供了基本的DOM
(文档对象模型)接口来解析和操作XML
文档。尽管它的API
相对较复杂,但它具有更多的功能和灵活性,适用于需要更高级控制的场景。
这些库都有各自的优点和适用场景。在选择库时,可以考虑以下因素:
- 对于简单的
XML
操作和小型文档,内置库xml.etree.ElementTree
是一个轻量级且易于使用的选择。- 如果需要更好的性能、更多的功能和高级特性(如
XPath
、XSLT
),可以选择lxml
库。- 如果希望将
XML
数据解析为Python
字典以便于处理,可以使用xmltodict
库。- 如果对
DOM
接口熟悉并且需要更多的灵活性和控制能力,可以考虑使用minidom
库。
# 说明
# 加载和读取xml文件,获取xml文档对象
from xml.dom import minidom
doc = minidom.parse(xmlfile)
# 获取xml文档根节点
root = doc.documentElement
# 节点属性
root.nodeName # 每个节点都有它的nodeName,nodeValue,nodeType属性
root.nodeValue # nodeValue是节点的值,只对本节点有效
root.nodeType # 节点类型;
root.ELEMENT_NODE
# 属性值的获取、修改、删除
root.getAttribute(attributeName) # 获取xml节点属性值
root.setAttribute(attributeName, value) # 修改或添加xml节点属性值
root.getElementsByTagName(TagName) # 根据标签获取xml节点对象集合
root.removeAttribute(attributeName) # 删除xml节点属性值
# 子节点的访问
root.childNodes # 获取子节点列表
root.childNodes[index].nodeValue # 获取xml节点值
root.firstChild # 访问第一个节点(相当于root.childNodes[0])
root.childNodes[0].data # 获得文本值
# 删除子节点
node.removeChild(childnode_in_node) # 删除node节点下面的子节点childnode_in_node
# 生成节点
node.createElement('activity') # 生成节点 # 文本节点.createTextNode('xxxxx')
(1)读取XML
XML
示例文件:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<breakfast_menu>
<food>
<name>Belgian Waffles</name>
<price>$5.95</price>
<calories>650</calories>
<cropRegion x="0" y="0" width="0000" height="1234"/>
</food>
<food>
<name>Strawberry Belgian Waffles</name>
<price>$7.95</price>
<calories>900</calories>
<cropRegion x="1" y="1" width="1111" height="2345"/>
</food>
<food>
<name>Berry-Berry Belgian Waffles</name>
<price>$8.95</price>
<calories>900</calories>
<cropRegion x="2" y="2" width="2222" height="3456"/>
</food>
<food>
<name>French Toast</name>
<price>$4.50</price>
<calories>600</calories>
<cropRegion x="3" y="3" width="3333" height="4567"/>
</food>
<food>
<name>Homestyle Breakfast</name>
<price>$6.95</price>
<calories>950</calories>
<cropRegion x="4" y="4" width="4444" height="5678"/>
</food>
</breakfast_menu>
DOM
解析XML
文件
from xml.dom import minidom
# 解析xml文件(句柄或文件路径)
doc = minidom.parse(r"D:\Desktop\simple.xml")
# doc = minidom.parseString() # 解析xml字符串
print(doc)
print("*"*20)
# 获得根节点
root_node = doc.documentElement
print(root_node)
# 节点名称
print(root_node.nodeName)
# 节点类型(元素节点,文本节点,属性节点)
print(root_node.nodeType)
# 所有子节点,为列表
print(root_node.childNodes)
print("*"*20)
# 通过节点名称寻找节点,返回列表
filename_node = root_node.getElementsByTagName('name')
print(filename_node)
print("*"*20)
# 子节点为文本节点,文本节点有data属性即为文本值
filename = filename_node[1].childNodes[0].data
print(filename)
print("*"*20)
# 读取指定属性值,root.setAttribute(attributeName, value)更新修改属性值
cropRegion_node = root_node.getElementsByTagName('cropRegion')
width = cropRegion_node[1].getAttribute("width")
print(width)
# 输出结果
<xml.dom.minidom.Document object at 0x0000016F45D0EDC0>
********************
<DOM Element: breakfast_menu at 0x16f45d011f0>
breakfast_menu
1
[<DOM Text node "'\n\t'">, <DOM Element: food at 0x16f45d01f70>, <DOM Text node "'\n\t'">, <DOM Element: food at 0x16f45d01b80>, <DOM Text node "'\n\t'">, <DOM Element: food at 0x16f45ccddc0>, <DOM Text node "'\n\t'">, <DOM Element: food at 0x16f458e0dc0>, <DOM Text node "'\n\t'">, <DOM Element: food at 0x16f45cf05e0>, <DOM Text node "'\n'">]
********************
[<DOM Element: name at 0x16f45d01dc0>, <DOM Element: name at 0x16f45d018b0>, <DOM Element: name at 0x16f45ccdd30>, <DOM Element: name at 0x16f45cf0af0>, <DOM Element: name at 0x16f45cf0280>]
********************
Strawberry Belgian Waffles
********************
1111
(2)写入XML
# 写入文件
DOM树对象.writexml(fh,indent='',addindent='\t',newl='\n',encoding='UTF-8')
# writexml()第一个参数是目标文件对象,第二个参数是根节点的缩进格式,第三个参数是其他子节点的缩进格式,第四个参数制定了换行格式,第五个参数制定了xml内容的编码。
# zip()函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。
# zip()方法在Python2和Python3中的不同:在Python3.x中为了减少内存,zip()返回的是一个对象。如需展示列表,需手动list()转换。
a = [1,2,3]
b = [4,5,6]
c = [4,5,6,7,8]
# 返回一个对象
zipped = zip(a,b)
print(zipped)
# list()转换为列表
print(list(zipped))
# 元素个数与最短的列表一致
print(list(zip(a,c)))
# 与zip相反,*zip()函数是zip()函数的逆过程,将zip对象变成原先组合前的数据
a1 = zip(*zip(a,b))
print(a1)
print(list(a1))
# 输出结果
<zip object at 0x0000016F45CD6200>
[(1, 4), (2, 5), (3, 6)]
[(1, 4), (2, 5), (3, 6)]
<zip object at 0x0000016F45CD0FC0>
[(1, 2, 3), (4, 5, 6)]
DOM
写XML
文件
# 写入XML文件
from xml.dom import minidom
# (1)创建DOM树对象
dom = minidom.Document()
# (2)创建根节点,每次都要用DOM对象来创建任何节点
root_node = dom.createElement("people")
# (3)用DOM对象添加根节点
dom.appendChild(root_node)
# 用DOM对象创建元素字节点
name_node = dom.createElement("name")
# 用父节点对象添加元素子节点
root_node.appendChild(name_node)
# 设置该节点的属性
name_node.setAttribute("sex","男")
name_node.setAttribute("height","180")
# 用DOM创建文本节点,把文本节点(文字内容)看成子节点
name_text = dom.createTextNode("小汤")
# 用添加了文本的节点对象(看成文本节点的父节点)添加文本节点
name_node.appendChild(name_text)
# 用DOM对象创建元素字节点
hobby_node = dom.createElement("hobby")
# 用父节点对象添加元素子节点
root_node.appendChild(hobby_node)
# 用添加了文本的节点对象(看成文本节点的父节点)添加文本节点
hobby_node.appendChild(dom.createTextNode("篮球"))
score_node = dom.createElement("score")
for item, value in zip(["语文", "数学", "英语", "理综"], [150, 150, 150, 300]):
elem = dom.createElement(item)
elem.appendChild(dom.createTextNode(str(value)))
score_node.appendChild(elem)
root_node.appendChild(score_node)
try:
with open(r"D:\Desktop\write.xml",'w',encoding='UTF-8') as fh:
# dom.writexml()第一个参数是目标文件对象,第二个参数是根节点的缩进格式,第三个参数是其他子节点的缩进格式,
# 第四个参数制定了换行格式,第五个参数制定了xml内容的编码。
dom.writexml(fh, indent='', addindent='\t', newl='\n', encoding='UTF-8')
print('OK')
except Exception as err:
print('错误:{err}'.format(err=err))
输出的XML
文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<people>
<name sex="男" height="180">小汤</name>
<hobby>篮球</hobby>
<score>
<语文>150</语文>
<数学>150</数学>
<英语>150</英语>
<理综>300</理综>
</score>
</people>
👀TXT
(1)读取TXT
源数据data.txt
内容如下:
name gender age hobby
小红 女 20 跑步
小汤 男 22 篮球
小李 男 24 足球
小ai 男 21 篮球
小张 男 25 篮球
小小 男 20 跳绳
小耿 男 25 羽毛球
操作txt
文件,read()
、readline()
、readlines()
、以及获取某一列内容,代码示例如下:
# (1)read()一次性读取所有文本
with open(r"D:\Desktop\data.txt", "r") as f: #打开文本
data1 = f.read() #读取文本
print(data1)
print("*"*20)
# (2)readline()读取第一行的内容
with open(r"D:\Desktop\data.txt", 'r') as f:
data2 = f.readline()
print(data2)
print("*"*20)
# (3)readlines()读取全部内容,以列表的格式返回结果
with open(r"D:\Desktop\data.txt", 'r') as f:
data3 = f.readlines()
print(data3)
for ann in data3:
# 去除文本中的换行符
ann = ann.strip('\n')
print(ann)
print("*"*20)
# (4)读取txt某一列数据,第一种方法
# 要读取第i列数据则可以读取每行的第i个数据再将其拼接起来
column_list = []
with open(r"D:\Desktop\data.txt", 'r') as f:
data = f.readlines()
for line in data:
# 去除文本中的换行符
ann = line.strip('\n')
a = ann.split("\t")
column_list.append(a[3])
print(column_list)
print("*"*20)
# (5)读取txt某一列数据,第二种方法
column_list2 = []
with open(r"D:\Desktop\data.txt", 'r') as f:
# 以行的形式进行读取文件
line2 = f.readline()
while line2:
ann2 = line2.strip('\n')
aa = ann2.split("\t")
column_list2.append(aa[2])
line2 = f.readline()
print(column_list2)
print("*"*20)
# (6)读取txt某一列数据,第三种方法
import codecs
column_list3 = []
with codecs.open(r"D:\Desktop\data.txt", mode = 'r') as f:
# 以行的形式进行读取文件
line3 = f.readline()
while line3:
ann3 = line3.strip('\n')
aaa = ann3.split("\t")
column_list3.append(aaa[1])
line3 = f.readline()
print(column_list3)
# 输出结果
name gender age hobby
小红 女 20 跑步
小汤 男 22 篮球
小李 男 24 足球
小ai 男 21 篮球
小张 男 25 篮球
小小 男 20 跳绳
小耿 男 25 羽毛球
********************
name gender age hobby
********************
['name\tgender\tage\thobby\n', '小红\t女\t20\t跑步\n', '小汤\t男\t22\t篮球\n', '小李\t男\t24\t足球\n', '小ai\t男\t21\t篮球\n', '小张\t男\t25\t篮球\n', '小小\t男\t20\t跳绳\n', '小耿\t男\t25\t羽毛球\n']
name gender age hobby
小红 女 20 跑步
小汤 男 22 篮球
小李 男 24 足球
小ai 男 21 篮球
小张 男 25 篮球
小小 男 20 跳绳
小耿 男 25 羽毛球
********************
['hobby', '跑步', '篮球', '足球', '篮球', '篮球', '跳绳', '羽毛球']
********************
['age', '20', '22', '24', '21', '25', '20', '25']
********************
['gender', '女', '男', '男', '男', '男', '男', '男']
(2)写入TXT
# 写入txt
hobby =["hobby", "跑步", "篮球", "足球", "篮球", "篮球", "跳绳", "羽毛球"]
name = ["name", "小红", "小汤", "小李", "小ai", "小张", "小小", "小耿"]
age = ["age", "20", "22", "24", "21", "25", "30", "25"]
with open(r"D:\Desktop\writeTXT.txt","a") as f:
length = len(age)
for i in range(length):
line = [hobby[i], name[i], age[i]]
lines = "\t".join(line)
# lines = hobby[i] + "\t" + name[i] + "\t" + age[i]
print(lines)
f.write(lines + '\n')
column_list = []
with open(r"D:\Desktop\writeTXT.txt","r") as f:
data = f.readlines()
# print(data)
for line in data:
# 去除文本中的换行符
ann = line.strip('\n')
a = ann.split("\t")
column_list.append(a[2])
print(column_list)
# 输出结果
hobby name age
跑步 小红 20
篮球 小汤 22
足球 小李 24
篮球 小ai 21
篮球 小张 25
跳绳 小小 30
羽毛球 小耿 25
['age', '20', '22', '24', '21', '25', '30', '25']
多谢!多谢!
笔者不才,请多交流!!!
欢迎大家关注预览我的博客Blog:HeartLoveLife
能力有限,敬请谅解!!