8. Pandas的DataFrame创建

Pandas的Dataframe是二维的,每一列都是一个Series结构。

8.1 字典数据创建DataFrame

DataFrame数据的创建和Series的创建类似,可以有很多方式。和Series一样也有字典类型的方式。

  • 字典方式创建DataFrame
import pandas as pd
df = pd.DataFrame({'name' : "hello the cruel world".split(),
                   'growth' : [100, 125, 150, 200]},
                   index = "jack tom mike nike".split())
print df

执行结果如下:

      growth   name
jack     100  hello
tom      125    the
mike     150  cruel
nike     200  world

最左侧的一列是index或者label和Series类似,第二列是growth列,第三列是name列。growth和name为该列的名字。需要特别注意的是DataFrame和其他表格数据不一样的是,DataFrame是列访问机制。例如要访问growth下的150这条数据的访问方式为:

import pandas as pd
df = pd.DataFrame({'name' : "hello the cruel world".split(),
                   'growth' : [100, 125, 150, 200]},
                   index = "jack tom mike nike".split())
print df['growth']['mike']
print df.growth['mike']
print df.name,type(df.name)
print df["name"]

程序执行结果:

150
150
jack    hello
tom       the
mike    cruel
nike    world
Name: name, dtype: object <class 'pandas.core.series.Series'>
jack    hello
tom       the
mike    cruel
nike    world
Name: name, dtype: object

df.name是Series的,这点儿很重要。

8.2 Numpy数据创建DataFrame

  • 通过numpy数据建立DataFrame
import numpy as np
import pandas as pd
df = pd.DataFrame(np.random.randn(10,3), columns = ["ca", "cb", "cc"], index = list("abcdefghij"))
print df

程序执行结果:

         ca        cb        cc
a -1.445673 -0.856954 -0.085766
b -0.276927 -0.181103 -1.120856
c  1.155409  0.114528  1.514519
d -0.304959 -1.099241 -0.018434
e  0.458164 -0.550848  0.396272
f -0.362203 -0.383894 -0.444436
g -0.755501 -0.148579 -0.910084
h -0.666200  0.713844  1.822668
i -1.278918 -2.055927 -0.404884
j  0.340294  1.437949 -0.119828

DataFrame构造函数的columns函数给出列的名字,index给出label标签或index位置信息,创建DataFrame的数据是numpy创建的二维的数据。

8.3 csv文件创建DataFrame

  • 从csv文件读取DataFrame数据,这里可以使用机器学习经典数据集iris.data数据作为测试数据,下载。iris.data文件的内容:
5.1,3.5,1.4,0.2,Iris-setosa
4.9,3.0,1.4,0.2,Iris-setosa
4.7,3.2,1.3,0.2,Iris-setosa
4.6,3.1,1.5,0.2,Iris-setosa
5.0,3.6,1.4,0.2,Iris-setosa
5.4,3.9,1.7,0.4,Iris-setosa
4.6,3.4,1.4,0.3,Iris-setosa

可以使用pandas的read_csv函数来读取这个文件里的数据到DataFrame数据里。

import pandas as pd
cols_name = ['sepal length', 'sepal width', 'petal length', 'petal width', 'class']
df = pd.read_csv("iris.data", names = cols_name)
print df

程序执行结果:

     sepal length  sepal width  petal length  petal width           class
0             5.1          3.5           1.4          0.2     Iris-setosa
1             4.9          3.0           1.4          0.2     Iris-setosa
2             4.7          3.2           1.3          0.2     Iris-setosa
3             4.6          3.1           1.5          0.2     Iris-setosa

iris.data文件里都是数据,而有些csv文件的第一行会给出每列数据的名字,例如股票交易信息类的csv文件通常都这样给出csv记录,可以从Nasdaq下载jd的历史交易记录,下载后存为jd.csv好了,和.py程序存储在同一个目录下。jd.csv的内容大致如下:

"date","close","volume","open","high","low"
"10:24","22.585","3,018,583","23.18","23.20","22.515"
"2018/10/23","23.2300","17943360.0000","22.6100","23.5900","22.3300"
"2018/10/22","23.5400","13934080.0000","23.8600","24.1100","23.3000"
"2018/10/19","23.0100","12953670.0000","23.9400","23.9499","22.9500"
"2018/10/18","23.3300","15580080.0000","23.5000","24.1321","23.2200"

它的第一行显然不是数据而是说明每列的数据是什么,这行数据是不能读入到DataFrame里的,应忽略掉。可以用pandas的read_csv先读一下这个文件。

import pandas as pd
df = pd.read_csv("jd.csv")
print df

程序执行结果如下:

          date   close         volume    open     high      low
0        10:24  22.585      3,018,583  23.180  23.2000  22.5150
1   2018/10/23  23.230  17943360.0000  22.610  23.5900  22.3300
2   2018/10/22  23.540  13934080.0000  23.860  24.1100  23.3000
3   2018/10/19  23.010  12953670.0000  23.940  23.9499  22.9500
4   2018/10/18  23.330  15580080.0000  23.500  24.1321  23.2200
5   2018/10/17  23.680  15368750.0000  24.520  24.6100  23.4600
6   2018/10/16  24.630  11679180.0000  24.500  24.7000  24.0800
7   2018/10/15  24.140  11132030.0000  24.110  24.6400  23.8000
8   2018/10/12  24.450  20191050.0000  24.540  24.9000  23.7400

这里有几个问题,1). index是自动用数字作为各行数据的index或label,一般应该用date做index或label作为股票分析时使用比较好,2).如果jd.csv文件的头几行是文件的说明,那么read_csv读的时候也会当作数据,这时应能忽略掉头几行非数据的信息。3). 数据读入后类型是否正确读出?

import pandas as pd

df = pd.read_csv("jd.csv", index_col = 0)
print df[:5]
print df.dtypes

程序执行结果:

             close         volume   open     high     low
date                                                     
10:24       22.585      3,018,583  23.18  23.2000  22.515
2018/10/23  23.230  17943360.0000  22.61  23.5900  22.330
2018/10/22  23.540  13934080.0000  23.86  24.1100  23.300
2018/10/19  23.010  12953670.0000  23.94  23.9499  22.950
2018/10/18  23.330  15580080.0000  23.50  24.1321  23.220
close     float64
volume     object
open      float64
high      float64
low       float64
dtype: object

  • 指定某列为label,通过指定read_csv函数的index_col形参为数据的第一列作为DataFrame的index或label,可将第一列date作为df这个DataFrame的label,避免用自动分配的整型数据作为label。

  • skiprows参数,volume的数据类型是object,很诡异,应该是数值型的数据比较好,所以在读入数据时可以指定相应列的数据类型。由于数据里的第1行的volume是' 3,018,583'这条数据和其下的其他数据的表示形式不一致,所以可以使用skiprows参数忽略这行数据。

import numpy as np
import pandas as pd
df = pd.read_csv("jd.csv", index_col = 0, dtype = {'volume' : np.float64},skiprows=[1])
print df[:5]
print df.dtypes

程序执行结果:

            close    volume   open     high    low
date                                              
2018/10/23  23.23  17943360  22.61  23.5900  22.33
2018/10/22  23.54  13934080  23.86  24.1100  23.30
2018/10/19  23.01  12953670  23.94  23.9499  22.95
2018/10/18  23.33  15580080  23.50  24.1321  23.22
2018/10/17  23.68  15368750  24.52  24.6100  23.46
close     float64
volume    float64
open      float64
high      float64
low       float64
dtype: object
  • header参数和names参数,数据里的第0行、第1行数据,一个是各字段名,和当日交易,pandas的read_csv会把第0行作为各个字段的名,也可自己指定字段名,忽略掉第0行的数据。
import numpy as np
import pandas as pd
df = pd.read_csv("jd.csv", index_col = 0, dtype = {'volume' : np.float64},skiprows=[0,1], header = 0, names = ["Close","Volume","Open","High","Low"])
print df[:5]
print df.dtypes

执行结果:

            Close    Volume   Open     High    Low
2018/10/22  23.54  13934080  23.86  24.1100  23.30
2018/10/19  23.01  12953670  23.94  23.9499  22.95
2018/10/18  23.33  15580080  23.50  24.1321  23.22
2018/10/17  23.68  15368750  24.52  24.6100  23.46
2018/10/16  24.63  11679180  24.50  24.7000  24.08
Close     float64
Volume    float64
Open      float64
High      float64
Low       float64
dtype: object
  • usecols参数,以上的例子是将数据全部读入,也可通过指定usecols参数,读入部分列的数据。
import numpy as np
import pandas as pd
df = pd.read_csv("jd.csv",
                skiprows=[1],  
                usecols = ['date','close',  'volume','open'], 
                index_col = 0,
                dtype = {'volume' : np.float64})

print df[:5]
print df.dtypes

程序执行结果:

            close    volume   open
date                              
2018/10/23  23.23  17943360  22.61
2018/10/22  23.54  13934080  23.86
2018/10/19  23.01  12953670  23.94
2018/10/18  23.33  15580080  23.50
2018/10/17  23.68  15368750  24.52
close     float64
volume    float64
open      float64
dtype: object
  • read_table函数,pandas里除了read_csv还有read_table函数也可以读取csv文件成DataFrame。
import pandas as pd
df = pd.read_csv("movies.dat", sep = "::",engine='python', index_col = 0)
print df[:5]

movies.dat文件可以从movielen下载,每天记录以::分割字段,部分内容如下。

1::Toy Story (1995)::Animation|Children's|Comedy
2::Jumanji (1995)::Adventure|Children's|Fantasy
3::Grumpier Old Men (1995)::Comedy|Romance
4::Waiting to Exhale (1995)::Comedy|Drama
5::Father of the Bride Part II (1995)::Comedy

通过read_table读回的数据:

                     Toy Story (1995)   Animation|Children's|Comedy
1                                                                  
2                      Jumanji (1995)  Adventure|Children's|Fantasy
3             Grumpier Old Men (1995)                Comedy|Romance
4            Waiting to Exhale (1995)                  Comedy|Drama
5  Father of the Bride Part II (1995)                        Comedy
6                         Heat (1995)         Action|Crime|Thriller

read_csv的nrows参数也很有用,如果数据文件很大,内存很小,读取数据不想全都读回,可以使用nrows函数指定读回的行数。

8.4 DataFrame存成csv

可以使用pandas的to_csv函数将DataFrame数据存储成csv文件。

import pandas as pd
df = pd.DataFrame({'name' : "hello the cruel world".split(),
                   'growth' : [100, 125, 150, 200]},
                   index = "jack tom mike nike".split())
print "*"* 10
print df
print "*"* 10
df.to_csv("out.csv", index_label = "index")
  • index_lable参数,to_csv函数里的index_label参数是给出index或label列的名字。输出的out.csv文件如下:
index,growth,name
jack,100,hello
tom,125,the
mike,150,cruel
nike,200,world

程序执行结果:

**********
      growth   name
jack     100  hello
tom      125    the
mike     150  cruel
nike     200  world
**********

8.5 Excel文件创建DataFrame

pandas还可以从Excel文件提取数据创建DateFrame数据,但需要平台支持Excel文件的读写模块,可以安装xlrd或openpyxl模块。

$ sudo pip install xlrd
  • read_excel函数读Excel里的数据,将上边jd.csv用excel打开,另存为jd.xls文件,然后用read_excel来读取Excel文件里的数据创建DataFrame。
import pandas as pd
df = pd.read_excel("jd.xls", index_col=0)
print df[:5]
  • 可以使用to_excel函数将数据写入Excel文件。
import pandas as pd
idx = list("abcdef")
val1 = range(10, 16)
val2 = range(19, 25)
df1 = pd.DataFrame({"math": val1, "eng" : val2}, index = idx)
print df1
df2 = pd.DataFrame({"chn": val1, "phy" : val2}, index = idx)
print df2
writer = pd.ExcelWriter("record.xls")
df1.to_excel(writer, sheet_name = "me")
df2.to_excel(writer, sheet_name = "cp")
writer.save()

to_excel函数的形参sheet_name指定表单名。

  • 读excel里多表单数据,创建DateFrame。上边代码将df1和df2数据写入Excel并生成record.xls文件,这个Excel文件里有两个表单:me和cp,现在用read_excel函数分别从两个表单里读取数据用于创建DataFrame。
import pandas as pd
df1 = pd.read_excel("record.xls", sheetname = "cp", index_col = 0)
print df1
print df1.index
df2 = pd.read_excel("record.xls", sheetname = "me", index_col = 0)
print df2
print df2.index

程序运行时结果:

   chn  phy
a   10   19
b   11   20
c   12   21
d   13   22
e   14   23
f   15   24
Index([u'a', u'b', u'c', u'd', u'e', u'f'], dtype='object')
   eng  math
a   19    10
b   20    11
c   21    12
d   22    13
e   23    14
f   24    15
Index([u'a', u'b', u'c', u'd', u'e', u'f'], dtype='object')

8.6 JSON数据创建DataFrame

pandas里提供to_json函数可以将DataFrame数据输出成json格式的数据文件。

import pandas as pd
df3 = pd.read_table("movies.dat", sep = "::",engine='python')
print df3
df3[:500].to_json("movies.json")
print "end"

程序执行完后,生成movies.json文件,可以用pandas的read_json函数将json文件里的数据读回并创建DataFrame数据。

import pandas as pd
df3 = pd.read_json("movies.json")
print df3