添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

pandas教程_02数据导入与导出.md

File metadata and controls

28PmlD.png

第二章:数据的导入与导出

数据导入和导出是pandas中很基础且重要的一个部分。pandas提供了很多不同格式数据的导入和导出方法,可以将其他格式数据转为DataFrame格式。我们可以将list、dict格式数据转为dataFrame格式,也可以从本地的csv、json等文本格式数据和sql、MongoDB等数据库中读取和保存数据等等。下面就分别以三大类介绍一些常见的数据格式的导入与导出。

当我们开始着手做一个数据分析项目时,选择和导入数据集是第一个步骤,而导出数据虽然非必需,但有时候我们也需要保存处理或者分析后的结果,方便下次使用。在pandas中,它已经为我们提供了很多不同格式数据的导入和导出方法,本节将具体介绍一些较为常用的方法,包括excel、csv文件以及数据库的导入导出等。

1. list、dict、np.array 格式数据

1.1 list

一般读取一个list,生成的结果如下:

pd.DataFrame([1,2,3,4])

运行结果:

如果读取的list中的每个元素都是一个元组,会发生什么呢?

pd.DataFrame([(1,2,3,4),(2,3,4,5)],columns = ['value1','value2','value3','value4'])

运行结果:

 	value1	value2	value3	value4
0     1	      2       3       4
1	  2	      3	      4	      5

如果忽略columns的话,第二个list的值不是列名,而是默认生成索引名,如下:

pd.DataFrame([(1,2,3,4),(2,3,4,5)],['value1','value2'])

运行结果:

 	    0	1	2	3
value1	1	2	3	4
value2	2	3	4   5

1.2 dict

这里我们以一个字典为数据,看下不同操作的结果有何不同。

data = {'a':[1,2],'b':[2,3]}

直接调用DataFrame进行读取的话,生成的DataFrame结构如下:

pd.DataFrame(data)
pd.DataFrame.from_dict(data)

运行结果:

0 1 2 1 2 3

需要说明的是:from_dict这个方法只有在pandas 0.23版本后才有,如果在早期的版本如0.19中调用会出现报错。 如果我们想以a,b作为索引,以list中的每个值分别为一列怎么操作呢?

pd.DataFrame.from_dict(data,orient='index',columns = ['value1','value2'])

运行结果:

	value1  value2
a	  1	      2
b	  2	      3

如果进一步想让a、b生成列的话,调用reset_index方法即可。

pd.DataFrame.from_dict(data,orient='index',columns = ['value1','value2']).reset_index().rename(columns = {'index':'key'})

运行结果:

	key	value1	value2
 0	a	  1	      2
1	b	  2	      3

但是如果我们想把字典的key和value分别生成两列,如何操作呢? 一种方法是:

pd.DataFrame(list(data.items()),columns = ['key','value'])
>>> 	key	value
>>> 0	a	[1, 2]
>>> 1	b	[2, 3]

还有一种方法依然是利用from_dict,不过就需要将value中的list提前转化成字符串,然后再进行操作即可。

1.3 np.array

numpy是比pandas更底层一些的数据操作工具,pandas的很多操作也是基于numpy进行的,比如numpy就支持直接读取txt文件。比如有这样一个txt文件:

1 10 0.45240003518120125 1.0000444454321133 0.10599999999999998 1.0599999999999998e-01 0.22999999999999998 0.472    2 20 0.43459179018909283 1.1133165687809157 0.07834109593771774 7.8341095937717736e-02 0.2089183326689947 0.3863815370463022    3 30 0.40767309706715493 1.269342944674328 0.07190653014564094 7.1906530145640940e-02 0.17795528298262073 0.4136993009059622    4 40 0.3859105442514819 1.3433376585083965 0.066153468987387 6.6153468987386999e-02 0.1477849202849159 0.261667203674047   

一共有4行8列的数据,数据间用空格隔开,表头带有%,那么读取的时候可以用loadtxt函数进行导入:

data = np.loadtxt('fit.txt', delimiter=None, comments='%',  usecols=(0, 1, 4,5))

运行结果:

array([[ 1.        , 10.        ,  0.106     ,  0.106     ],
       [ 2.        , 20.        ,  0.0783411 ,  0.0783411 ],
       [ 3.        , 30.        ,  0.07190653,  0.07190653],
       [ 4.        , 40.        ,  0.06615347,  0.06615347]])

可以看到数据自动剔除了表头,并且只用了其中指定的列。接下来就可以将array导入到pandas中:

Data = pd.DataFrame(data, index = np.arange(len(data)), columns=['a','b','c','d'])

我们就可以得到类似用list构建DataFrame的效果了:

	  a	  b	        c	          d
0	1.0	  10.0	0.106000	0.106000
1	2.0	  20.0	0.078341	0.078341
2	3.0   30.0	0.071907	0.071907
3	4.0	  40.0	0.066153	0.066153

1.4 其他方式

当然需要导入文本并不规则的时候,可以考虑直接利用python中的文件读取来一行一行的读取文件,然后利用json或者re等字符串处理包来处理数据,最后整合成DataFrame:

with open(path, "r") as load_f:
     l = f.readlines()

当然这个方法要结合具体的数据来看,这里就不展开介绍了。

2. 文本格式数据格式数据

2.1 CSV文件

2.1.1 导入CSV文件

常用参数解析:

pandas.read_csv(filepath_or_buffer, sep=',', header='infer', names=None, indxe_col=None)
  • filepath_or buffer: str, path object or file-like object。指定传入的文件路径,必须传入的参数。
  • sep: str。指定分隔符,默认是逗号分隔符。
  • header: int, list or int。指定行数用来作为列名。默认是如果没有传入names参数,则header=0,用第一行作为列名,否则header=None,以传入的names作为列名。另外如果传入的是list,例如[0,1,3],则是以第1、2、4这些行作为多级列名,且中间的行,第3行会被忽略,数据从第5行开始。
  • names: array-like, optional。指定文件的列名。如果文件中没有标题行,建议传入此参数。
  • index_col: int, str, or sequence of int / str, or False。指定文件的索引,默认为None。
  • ex1.csv内容如下:

    ID,name,age,city,message
    A001, 小明,18, 北京,hello
    A002, 小王,20, 杭州,world
    A003, 小北,21, 上海,hello
    A004, 张三,18, 北京,pandas
    

    导入ex1.csv

    df = pd.read_csv('examples/ex1.csv')
    

    运行结果:

     	 ID	    name	age	  city	 message
    0	A001	小明	    18	  北京	  hello
    1	A002	小王	    20	  杭州	  world
    2	A003	小北	    21	  上海	  hello
    3	A004	张三	    18	  北京	  pandas
    

    ex2.csv文件没有标题行

    A001|小明|18|北京|hello
    A002|小王|20|杭州|world
    A003|小北|21|上海|hello
    A004|张三|18|北京|pandas
    

    设置sep和header参数,导入ex2.csv

    df2 = pd.read_csv('examples/ex2.csv',sep='|',header=None)
    

    运行结果:

    	0	    1	  2	    3	  4
    0	A001	小明	  18	北京	  hello
    1	A002	小王	  20	杭州	  world
    2	A003	小北	  21	上海	  hello
    3	A004	张三	  18	北京	  pandas
    

    设置sep和names参数,此时header默认为None

    df3 = pd.read_csv('examples/ex2.csv',sep='|', names=['ID','name','age','city','message
    

    运行结果:

     	ID	   name	  age    city	 message
    0	A001	小明	    18	  北京	  hello
    1	A002	小王	    20	  杭州	  world
    2	A003	小北	    21	  上海	  hello
    3	A004	张三	    18	  北京	  pandas
    

    对ex1.csv设置多级标题,将第1、2、4行作为标题,数据从第5行开始

    df4 = pd.read_csv('examples/ex1.csv',header=[0,1,3])
    

    对ex1.csv设置多级标题,将第1、2、4行作为标题,数据从第5行开始

     	ID	  name	age	  city	message
     	A001  小明   18	  北京	hello
    	A003  小北   21	  上海	hello
    0	A004   张三	18    北京  	pandas
    

    导入ex1.csv,指定索引为message一列

    df5 = pd.read_csv('examples/ex1.csv',index_col='ID')
    

    运行结果:

      	  name	  age	city  message
    A001	小明	  18	北京	  hello
    A002	小王	  20	杭州	  world  
    A003	小北	  21	上海	  hello
    A004	张三	  18	北京	  pandas
    

    导入ex1.csv,指定第1和2列作为多重索引

    df6 = pd.read_csv('examples/ex1.csv',index_col=[0,1])
    

    运行结果:

     		    age	  city	  message
    ID	  name			
    A001	小明	  18	北京	  hello
    A002	小王	  20	杭州	  world
    A003	小北	  21	上海	  hello
    A004	张三	  18	北京	  pandas
    

    2.1.2 导出csv数据

    参用参数解析:

    DataFrame.to_csv(path_or_buf, index=True, header=True, sep=',', encoding='utf-8')
    
  • path_or_buf: str or file handle。指定保存文件路径,必须传入的参数,默认为None。
  • index: bool。导出的csv是否包含索引,默认为True。
  • header: bool or list of str。导出的csv是否包含标题行,默认为True。
  • sep: str。指定导出的csv文件的分隔符,默认为逗号分隔符。
  • encoding: str。指定导出的csv文件的编码,默认为utf-8。
  • # 导出文件
    df.to_csv("output/out_ex1.csv",index=False)
    

    2.2 excel文件

    2.2.1 导入excel文件

    常用参数解析:

    pd.read_excel(io, sheet_name=0, header=0, names=None, index_col=None)
    

    read_excel和read_csv的用法差不多,一个需要注意的参数是sheet_name。这个参数是指定读取该excel中具体哪个表的数据,默认为0,即为第一个表。如果传入1,则为第2个表;可指定传入表名,如"Sheet1";也可传入多个表,如[0,'Sheet3'],传入第一个表和名为'Sheet3'的表。 读取ex1.xlsx文件,默认为读取第一个表

    df = pd.read_excel("examples/ex1.xlsx")
    

    运行结果:

    >>> col_1 col_2 col_3 col_4 col_5 >>> 0 a b c d 1 >>> 1 e f g h 2 >>> 2 i j k l 3 >>> 3 m n o p 4

    读取ex1.xlsx文件的第2个表

    df2 = pd.read_excel("examples/ex1.xlsx",sheet_name=1)
    

    运行结果:

     	col_1	col_2	col_3	col_4	col_5
    0	  aa	  bb	  cc	  dd	  11
    1	  ee	  ff	  gg	  hh	  22
    2	  ii	  jj	  kk	  ll	  33
    3	  mm	  nn	  oo	  pp      44
    

    读取ex1.xlsx文件的第2个表和名为"Sheet3"的表,返回的是对象是OrderedDict。OrderedDict是dict的子类,与dict不同的是,它记住了内容的顺序。

    od = pd.read_excel("examples/ex1.xlsx",sheet_name=[1,'Sheet3'])
    

    运行结果:

    OrderedDict([(1,   col_1 col_2 col_3 col_4  col_5
                      0    aa    bb    cc    dd     11
                      1    ee    ff    gg    hh     22
                      2    ii    jj    kk    ll     33
                      3    mm    nn    oo    pp     44),
                 ('Sheet3',   col_1 col_2 col_3 col_4  col_5
                      0   aaa   bbb   ccc   ddd    111
                      1   eee   fff   ggg   hhh    222
                      2   iii   jji   kkk   lll    333
                      3   mmm   jjj   ooo   ppp    444)])
    

    在这个orderedDict中,有两个key。第一个key是1,对应的value为该表的内容;第二个key是'Sheet3',对应的value是Sheet3表格的内容。我们选取key,就能得到相应的value。

    od[1]
    

    运行结果:

     	col_1	col_2	col_3	col_4	col_5
    0	  aa	  bb	  cc	  dd	  11
    1	  ee	  ff	  gg	  hh	  22
    2	  ii	  jj	  kk	  ll	  33
    3	  mm	  nn	  oo	  pp      
    
    od['Sheet3']
    

    运行结果:

     	col_1	col_2	col_3	col_4	col_5
    0	  aaa	  bbb	  ccc	  ddd	  111
    1	  eee	  fff	  ggg	  hhh	  222
    2	  iii	  jji	  kkk	  lll	  333
    3	  mmm	  jjj	  ooo	  ppp	  444
    

    2.2.2 导出excel文件

    常用参数解析:

    DataFrame.to_excel(excel_writer, sheet_name='Sheet1',index=True)
    
  • excel_writer: str。指定保存文件路径。
  • sheet_name: str。指定excel文件的表名,默认为’Sheet1‘。
  • index:bool。是否保存索引,默认为True。
  • df.to_excel('output/out_ex1.xlsx')
    df.to_excel('output/out_ex2.xlsx',sheet_name='结果',index=False)
    

    2.3 txt文件

    2.3.1 导入txt文件

    常用参数解析:

    pandas.read_table(filepath_or_buffer, sep='\t', header='infer', names=None, index_col=None)
    

    read_table与read_csv的唯一区别是,read_csv默认的sep参数是逗号分隔符,而read_table默认是'\t',制表符。所以这两个方法是通用的,只要设置好分隔符,都可以读取csv和txt文件。 ex3.txt文件的内容如下:

    ID   	name   	age  	 city
    A001 	  小明   	18	北京
    A002 	  小王   	20	杭州
    A003 	  小北   	21	上海
    A004 	  张三   	18	北京
    A005 	  李四   	23	上海
    A006 	  小思   	24	广州
    A007 	  王五   	24	上海
    A008 	  小哇   	19	北京
    A009 	  黎明   	25	上海
    A010      夕阳       23  杭州
    

    导入ex3.txt文件

    df = pd.read_table('examples/ex3.txt')
    

    运行结果:

    	 ID	    name  age	city
    0	A001	小明	  18	北京
    1	A002	小王	  20	杭州
    2	A003	小北	  21	上海
    3	A004	张三	  18	北京
    4	A005	李四	  23	上海
    5	A006	小思	  24	广州
    6	A007	王五	  24	上海
    7	A008	小哇	  19	北京
    8	A009	黎明	  25	上海
    9	A010	夕阳	  23	杭州
    

    将sep参数设置为逗号,同样能读取ex1.csv文件

    df2 = pd.read_table('examples/ex1.csv',sep=',')
    

    运行结果:

     	ID	  name	  age	city	message
    0	A001	小明	  18	北京	    hello
    1	A002	小王	  20	杭州	    world
    2	A003	小北	  21	上海	    hello
    3	A004	张三	  18	北京	    pandas
    

    2.3.2 导入txt文件

    使用to_csv的方法

    df2.to_csv('output/ex3.txt',sep='\t')
    

    2.4 csv和xlsx的选择

    当我们可以选择保存为csv或者xlsx格式,方便下次可以使用的时候,是选择保存为csv还是excel呢?除了考虑csv和excel文件大小之外(相同的数据下excel文件比csv文件小),这里可以考虑下read_csv和read_xlsx的性能问题。在stackoverflow上有人对这两种导入方法进行了一个简单的测试。

    测试文件:同样的数据集(分别是320MB的csv文件和16MB的xlsx文件)

    电脑硬件:i7-7700k,SSD

    python环境:Anaconda Python 3.5.3, pandas 0.19.2

    | | 用时 | |:----:|:----:|:----:|:----:| | pd.read_csv('foo,csv') | 2s | | pd.read_excel('foo.xlsx') | 15.3s | | df.to_csv('bar.csv',index=False) | 10.5s | | df.to_excel('bar.xlsx',index=False) | 34.5s |

    2.5 json

    2.5.1 导入json文件

    常用参数解析:

    pandas.read_json(path_or_buf=None, orient=None, typ='frame')
    
  • path_or_buf: 指定文件路径,默认为None,必须传入的参数。
  • orient: json字符串格式,默认为None。这里有split,records,index,columns,values五种选择可选。
  • typ: 要转换为series还是dataframe,默认为frame。当typ=frame时,orient可选split/records/index,默认为columns;当typ=series,orient可选split/records/index/columns/value,orient默认为index。
  • split格式: dict like {index -> [index], columns -> [columns], data -> [values]}, 例如下面的ex4.json文件。

    {"index":[1,2,3,4],
         "columns":["ID","age","city","name"],
         "data":[["A001",18,"北京","小明"],
                 ["A002",20,"杭州","小王"],
                 ["A003",21,"上海","小北"],
                 ["A004",18,"北京","张三"]]
    

    导入ex4.json

    df = pd.read_json('examples/ex4.json',orient="split")
    

    运行结果:

     	ID	  age	  city    	name
    1	A001	18	  北京	    小明
    2	A002	20	  杭州	    小王
    3	A003	21	  上海	    小北
    4	A004	18	  北京	    张三
    

    records格式:list like [{column -> value}, ..., {column -> value}],例如下面的ex5.json文件。

    [{"ID":"A001","name":"小明","age":18,"city":"北京"},
    {"ID":"A002","name":"小王","age":20,"city":"杭州"},
    {"ID":"A003","name":"小北","age":21,"city":"上海"},
    {"ID":"A004","name":"张三","age":18,"city":"北京"}]
    

    导入ex5.json

    df1 = pd.read_json('examples/ex5.json',orient="records")
    

    运行结果同上。 如果是转为series格式:

    pd.read_json('examples/ex5.json',orient="records",typ="series")
    

    运行结果:

    0    {'ID': 'A001', 'name': '小明', 'age': 18, 'city'...
    1    {'ID': 'A002', 'name': '小王', 'age': 20, 'city'...
    2    {'ID': 'A003', 'name': '小北', 'age': 21, 'city'...
    3    {'ID': 'A004', 'name': '张三', 'age': 18, 'city'...
    dtype: object
    

    index格式: dict like {index -> {column -> vlaue}},例如下面的ex6.json文件。

    {"1": {"ID":"A001","name":"小明","age":18,"city":"北京"},
    "2": {"ID":"A002","name":"小王","age":20,"city":"杭州"},
    "3":{"ID":"A003","name":"小北","age":21,"city":"上海"},
    "4":{"ID":"A004","name":"张三","age":18,"city":"北京"},
    

    导入ex6.json

    df2 = pd.read_json('examples/ex6.json',orient="index")
    

    运行结果:

     	ID	  age	  city	  name  
    1	A001	18	  北京	  小明
    2	A002	20	  杭州	  小王
    3	A003	21	  上海	  小北
    4	A004	18	  北京	  张三
    

    如果是转为series格式:

    pd.read_json('examples/ex6.json',orient="index",typ="series")
    

    运行结果:

    0    {'ID': 'A001', 'name': '小明', 'age': 18, 'city'...
    1    {'ID': 'A002', 'name': '小王', 'age': 20, 'city'...
    2    {'ID': 'A003', 'name': '小北', 'age': 21, 'city'...
    3    {'ID': 'A004', 'name': '张三', 'age': 18, 'city'...
    dtype: object
    

    columns格式: dict like {column -> {index -> value}},例如下面的ex7.json文件。当typ='frame'时,orient默认为这个格式。

    "ID":{"1":"A001","2":"A002","3":"A003","4":"A004"}, "name":{"1":"小明","2":"小王","3":"小北","4":"张三"}, "age":{"1":18,"2":20,"3":21,"4":18}, "city":{"1":"北京","2":"杭州","3":"上海","4":"北京"},

    导入ex7.json

    df3 = pd.read_json('examples/ex7.json',orient="columns")
    df3 = pd.read_json('examples/ex7.json')
    

    运行结果:

     	ID	    name  age	city
    1	A001	小明	  18	北京
    2	A002	小王	  20	杭州
    3	A003	小北	  21	上海
    4	A004	张三	  18	北京
    

    用columns格式读取ex6.json,其实与index格式的结果是行列的转置。

    df4 = pd.read_json('examples/ex6.json',orient="columns")
    

    运行结果:

     	  1	      2	      3	      4
    ID	 A001	A002	A003	A004
    ge	 18	    20	    21	    18
    city 北京	杭州	    上海	    北京
    name 小明	小王	    小北	    张三
    

    values格式: just the values array,例如下面的ex8.json文件。

    [["A001","小明",18,"北京"],
    ["A002","小王",20,"杭州"],
    ["A003","小北",21,"上海"],
    ["A004","张三",18,"北京"]]
    

    导入ex8.json

    df5 = pd.read_json('examples/ex8.json',orient="values")
    

    运行结果:

     	0	    1	  2	    3
    0	A001	小明	  18	北京
    1	A002	小王	  20	杭州
    2	A003	小北	  21	上海
    3	A004	张三	  18	北京
    

    2.5.2 导出json文件

    常用参数解析:

    DataFrame.to_json(path_or_buf=None, orient=None,index=True)
    
  • orient: string。指定导出json的格式。DataFrame默认是columns,Series默认是index
  • dataframe导出json,命名为out_ex4.json

    df.to_json("output/out_ex4.json")
    

    series导出json,命名为out_ex5.json

    se = pd.read_json('examples/ex6.json',orient="index",typ="series")
    se.to_json("output/out_ex5.json")
    

    3 数据库

    3.1 MySQL

    在开始之前,请确保环境中的python为3.x版本,且已经安装并开启mysql服务。这里我们使用pymysql库来连接mysql。首先需要通过pip安装pymysql。安装后,可以通过import语句检验是否已经安装成功。如果没有报错,则说明安装成功。

    pip install pymysql
    
    import pymysql
    # 打开数据库连接
    # 注意在进行这一步之前要先创建好数据库。如果数据库不存在,这一步会报错。
    conn = pymysql.connect(host="localhost",user="username",password="password",db="dbtest")
    # 创建一个游标对象
    cursor = conn.cursor()
    

    3.1.1 数据导入mysql

    # 创建数据库表
    sql_createTb = """CREATE TABLE user (
                     ID CHAR(4) NOT NULL,
                     name CHAR(20),
                     age INT,
                     city CHAR(20)
    # 执行SQL语句
    cursor.execute(sql_createTb)
    # 插入数据
    insert1 = "INSERT INTO user(ID,name,age,city) values('A001','小明',18,'北京')"
    insert2 = "INSERT INTO user(ID,name,age,city) values('A002','小王',20, '杭州');"
    insert3 = "INSERT INTO user(ID,name,age,city) values('A003','张三',18, '北京');"
    insert4 = "INSERT INTO user(ID,name,age,city) values('A004','张三',18, '北京');"
    insert5 = "INSERT INTO user(ID,name,age,city) values('A005','李四',23, '上海');"
    insert6=  "INSERT INTO user(ID,name,age,city) values('A006','小思',24, '广州');"
    # 执行SQL语句
    for sql_insert in [insert1,insert2,insert3,insert4,insert5,insert6]:
        cursor.execute(sql_insert)   
    # pymysql默认是没有开始自动提交事务的
    # 所以在对更新数据库的时候,一定要手动提交事务
    conn.commit()
    # 更新数据
    sql_update = "update user set city='深圳' where ID='A001'"
    # 执行SQL语句
    cursor.execute(sql_update)
    # 提交事务
    conn.commit()
    # 删除数据
    sql_delete = "delete from user where ID='A004'"
    # 执行SQL语句
    cursor.execute(sql_delete)
    # 提交事务
    conn.commit()
    

    3.1.2 读取mysql数据

    通过sql语句查询数据

    # 查询数据
    sql_search  = "SELECT * FROM user"
    cursor.execute(sql_search)
    # 查看结果
    results = cursor.fetchall()
    results
    

    运行结果:

     (('A001', '小明', 18, '深圳'),
      ('A002', '小王', 20, '杭州'),
      ('A003', '张三', 18, '北京'),
      ('A005', '李四', 23, '上海'),
      ('A006', '小思', 24, '广州')
    

    将结果转换为dataframe格式

    df = pd.DataFrame(list(results))
    df.columns = ['ID','name','age','city']
    

    运行结果:

        ID	    name	age	  city
    0	A001	小明	    18	  深圳
    1	A002	小王	    20	  杭州
    2	A003	张三	    18	  北京
    3	A005	李四	    23	  上海
    4	A006	小思	    24	  广州
    

    关闭数据库连接: