IO Tools (Text, CSV, HDF5, ...)

原文:http://pandas.pydata.org/pandas-docs/stable/io.html

译者:飞龙 UsyiyiCN

校对:(虚位以待)

pandas I / O API是一组顶级的reader函数,像pd.read_csv()访问,通常返回一个pandas对象。

对应的writer函数是对象方法,像df.to_csv()

Here是其中一些IO方法的非正式性能比较。

注意

For examples that use the StringIO class, make sure you import it according to your Python version, i.e. from StringIO import StringIO for Python 2 and from io import StringIO for Python 3.

CSV & Text files

用于读取文本文件的两个主力功能(a.k.a.平面文件)是read_csv()read_table()他们都使用相同的解析代码智能地将表格数据转换为DataFrame对象。有关某些高级策略,请参阅cookbook

Parsing options

read_csv()read_table()

Basic

filepath_or_buffer
各种
要么是文件的路径(strpathlib.Pathpy._path.local.LocalPath),URL(包括http, ftp和S3位置),或任何具有read()方法(例如打开的文件或StringIO)的对象。
sep
: str, defaults to ',' for read_csv(), \t for read_table()
分隔符使用。如果sep为None,将尝试自动确定这一点。长度大于1个字符且与'\s+'不同的分隔符将被解释为正则表达式,将强制使用Python解析引擎,并忽略数据中的引号。正则表达式示例:'\\r\\t'
delimiter
str,默认None
sep的备用参数名称。
delim_whitespace
boolean,default False

指定是否使用空格(例如' ''\t')作为分隔符。相当于设置sep='\s+'如果此选项设置为True,则不应为delimiter参数传入任何内容。

版本0.18.1中的新功能:支持Python解析器。

Column and Index Locations and Names

标题
int或ints列表,默认'infer'
要用作列名称的行号,以及数据的开始。如果没有传递names,默认行为就像header=0,否则就像header=None显式传递header=0,以便能够替换现有名称。头部可以是指定列的多索引的行位置的整数列表,例如[0,1,3]未指定的插入行将被跳过(例如,在此示例中跳过2)。请注意,如果skip_blank_lines=True,此参数将忽略已注释的行和空行,因此header = 0表示数据的第一行,而不是文件的第一行。
名称
数组样,默认None
要使用的列名称列表。如果文件不包含标题行,则应明确传递header=None除非mangle_dupe_cols=True,此列表中的重复项是不允许的,这是默认值。
index_col
int或序列或False,默认None
用作DataFrame的行标签的列。如果给出序列,则使用MultiIndex。如果您在每行末尾都有带分隔符的格式不正确的文件,则可以考虑index_col=False强制将pandas强制为而不是使用第一列作为索引)。
usecols
数组样,默认None
返回列的子集。此数组中的所有元素必须是位置(即,文档列中的整数索引)或对应于用户在名称中提供或从文档标题行推断的列名称的字符串。例如,有效的usecols参数将是[0,1,2]或['foo','bar','baz']。使用此参数会导致更快的解析时间和更低的内存使用率。
as_recarray
boolean,默认False

DEPRECATED:此参数将在以后的版本中删除。请改用pd.read_csv(...).to_records()

在解析数据后,返回NumPy recarray而不是DataFrame。如果设置为True,则此选项优先于squeeze参数。此外,由于行索引在此类格式中不可用,因此将忽略index_col参数。

boolean,默认False
如果解析的数据只包含一列,则返回一个Series。
字首
str,默认None
在没有标题时添加到列号的前缀,例如'X'代表X0,X1,...
mangle_dupe_cols
布尔值,默认True
重复的列将被指定为“X.0”...“X.N”,而不是“X”...“X”。如果在列中存在重复的名称,则传入False将导致覆盖数据。

General Parsing Configuration

dtype
输入列的名称或字典 - >类型,默认None
数据或列的数据类型。例如。 {'a': np.float64, 'b': np.int32} t0>(不支持engine='python')。使用str对象来保留而不是解释dtype。
驱动
{'c''python'}
解析器引擎使用。C引擎速度更快,而python引擎目前更加完善。
转换器
dict,默认None
说明转换某些列中的值的函数。键可以是整数或列标签。
true_values
列表,默认None
要考虑的值为True
false_values
列表,默认None
要考虑的值为False
skipinitialspace
boolean,默认False
跳过分隔符后的空格。
skiprows
列表状或整数,默认None
要跳过的行号(0索引)或要跳过的行数(int)在文件的开头。
skipfooter
int,默认0
要跳过的文件底部的行数(不支持engine ='c')。
skip_footer
int,默认0
DEPRECATED:使用skipfooter参数,因为它们是相同的
nrows
int,默认None
要读取的文件的行数。适用于读取大文件的片段。
内存不足
布尔值,默认True
在内部以块的方式处理文件,导致解析时内存使用较少,但可能是混合类型推断。要确保没有混合类型,请设置False,或使用dtype参数指定类型。请注意,无论如何,整个文件都读入单个DataFrame,请使用chunksizeiterator参数以块形式返回数据。(只有C解析器有效)
buffer_lines
int,默认无
DEPRECATED:此参数将在未来版本中删除,因为其值不受解析器的影响
compact_ints
boolean,default False

DEPRECATED:此参数将在以后的版本中删除

如果compact_intsTrue,则对于任何整数为dtype的列,解析器将尝试将其作为最小整数dtype根据use_unsigned参数的规范,可以是有符号或无符号。

use_unsigned
boolean,default False

DEPRECATED:此参数将在以后的版本中删除

如果整数列被压缩(即compact_ints=True),请指定该列是否应压缩到最小有符号或无符号整数dtype。

memory_map
boolean,default False
如果为filepath_or_buffer提供了文件路径,则将文件对象直接映射到内存上,并从中直接访问数据。使用此选项可以提高性能,因为不再有任何I / O开销。

NA and Missing Data Handling

na_values
标量,str,列表式或dict,默认None
可识别为NA / NaN的其他字符串。如果dict通过,特定的每列NA值。By default the following values are interpreted as NaN: '-1.#IND', '1.#QNAN', '1.#IND', '-1.#QNAN', '#N/A N/A', '#N/A', 'N/A', 'NA', '#NA', 'NULL', 'NaN', '-NaN', 'nan', '-nan', ''.
keep_default_na
布尔值,默认True
如果指定了na_values且keep_default_na为False,则将覆盖默认NaN值,否则将追加到。
na_filter
布尔值,默认True
检测缺失值标记(空字符串和na_values的值)。在没有任何NA的数据中,传递na_filter=False可以提高读取大文件的性能。
详细
boolean,默认False
指示放置在非数字列中的NA值的数量。
skip_blank_lines
布尔值,默认True
如果True,则跳过空白行,而不是解释为NaN值。

Datetime Handling

parse_dates
布尔值或整数或名称列表或列表或dict列表,默认False
  • 如果True - >尝试解析索引。
  • 如果[1, 2, 3] - >尝试将列1,2,3分别解析为单独的日期列。
  • 如果[[1, 3]] - >合并列1和3并解析为单个日期列。
  • 如果{'foo' [1, 3]} 列1,3作为日期和调用结果'foo'。iso8601格式的日期存在快速路径。
infer_datetime_format
boolean,默认False
If True and parse_dates is enabled for a column, attempt to infer the datetime format to speed up the processing.
keep_date_col
boolean,默认False
如果True和parse_dates指定合并多个列,则保留原始列。
date_parser
功能,默认None
用于将字符串列序列转换为datetime实例数组的函数。默认使用dateutil.parser.parser进行转换。Pandas将尝试以三种不同的方式调用date_parser,如果发生异常,则推进到下一个:1)将一个或多个数组(由parse_dates定义)作为参数传递; 2)将由parse_dates定义的列中的字符串值连接(逐行)到单个数组中,并传递;和3)对于每一行,使用一个或多个字符串(对应于由parse_dates定义的列)作为参数调用date_parser一次。
日间
boolean,默认False
DD / MM格式日期,国际和欧洲格式。

Iteration

迭代器
boolean,默认False
返回TextFileReader对象以进行迭代或使用get_chunk()获取块。
chunksize
int,默认None
返回TextFileReader对象以进行迭代。请参阅下面的iterating and chunking

Quoting, Compression, and File Format

压缩
: {'infer', 'gzip', 'bz2', 'zip', 'xz', None}, default 'infer'

用于磁盘上数据的即时解压缩。如果'infer',则使用gzip,bz2,zip或xz,如果filepath_or_buffer是分别以'.gz','.bz2','.zip'或'.xz'结尾的字符串,否则不进行解压缩。如果使用'zip',ZIP文件必须只包含一个要读入的数据文件。设置为None,表示无解压缩。

新版本0.18.1:支持'zip'和'xz'压缩。

数千
str,默认None
千位分隔符。
十进制
str,default '.'
识别为小数点的字符。例如。对欧洲数据使用​​','
float_precision
字符串,默认为无
指定C引擎应该为浮点值使用哪个转换器。对于普通转换器,选项为None,对于高精度转换器,选项为high,对于往返转换器选项为round_trip
线性判定器
str(长度1),默认None
将文件拆分成行的字符。只有C解析器有效。
匹配
str(length 1)
用于表示带引号项目的开始和结束的字符。引号项可以包含分隔符,它将被忽略。
引用
int或csv.QUOTE_*实例,默认0
每个csv.QUOTE_*常量的控制字段引用行为。使用QUOTE_MINIMAL(0),QUOTE_ALL(1),QUOTE_NONNUMERIC(2)或QUOTE_NONE
双引号
布尔值,默认True
When quotechar is specified and quoting is not QUOTE_NONE, indicate whether or not to interpret two consecutive quotechar elements inside a field as a single quotechar element.
escapechar
str(长度1),默认None
引号时用于转义分隔符的单字符字符串为QUOTE_NONE
评论
str,默认None
表示不应解析行的剩余部分。如果在行的开头找到,则该行将完全被忽略。此参数必须为单个字符。与空行一样(只要skip_blank_lines=True),完全注释的行就会被参数忽略,而不会被skiprows忽略。例如,如果comment='#',用header = 0解析'#empty \ na,b,c \ n1,2,3' ,b,c'被当作报头。
编码
str,默认None
在读/写时用于UTF的编码(例如'utf-8')。Python标准编码列表
方言
str或csv.Dialect实例,默认None
如果None默认为Excel方言。如果sep长于1个字符,则忽略。有关详细信息,请参阅csv.Dialect文档。
tupleize_cols
boolean,默认False
将列上的元组列表保留为原样(默认是将列转换为MultiIndex)。

Error Handling

error_bad_lines
布尔值,默认True
默认情况下,具有太多字段的行(例如,具有太多逗号的csv行)将引发异常,并且不会返回DataFrame。如果False,那么这些“坏行”将从返回的DataFrame中删除(仅对C解析器有效)。请参阅下面的bad lines
warn_bad_lines
布尔值,默认True
如果error_bad_lines为False,而warn_bad_lines为True,则会输出每个“坏行”的警告(仅对C解析器有效)。

考虑一个典型的CSV文件,在这种情况下,包含一些时间序列数据:

In [1]: print(open('foo.csv').read())
date,A,B,C
20090101,a,1,2
20090102,b,3,4
20090103,c,4,5

read_csv的默认值是创建具有简单编号行的DataFrame:

In [2]: pd.read_csv('foo.csv')
Out[2]: 
       date  A  B  C
0  20090101  a  1  2
1  20090102  b  3  4
2  20090103  c  4  5

在索引数据的情况下,您可以传递要用作索引的列号或列名:

In [3]: pd.read_csv('foo.csv', index_col=0)
Out[3]: 
          A  B  C
date             
20090101  a  1  2
20090102  b  3  4
20090103  c  4  5
In [4]: pd.read_csv('foo.csv', index_col='date')
Out[4]: 
          A  B  C
date             
20090101  a  1  2
20090102  b  3  4
20090103  c  4  5

您还可以使用列列表创建层次索引:

In [5]: pd.read_csv('foo.csv', index_col=[0, 'A'])
Out[5]: 
            B  C
date     A      
20090101 a  1  2
20090102 b  3  4
20090103 c  4  5

dialect关键字在指定文件格式时具有更大的灵活性。默认情况下,它使用Excel方言,但您可以指定方言名称或csv.Dialect实例。

假设您有未封闭的引号的数据:

In [6]: print(data)
label1,label2,label3
index1,"a,c,e
index2,b,d,f

默认情况下,read_csv使用Excel方言,并将双引号作为引号字符,这会导致它在找到换行符之前找到换行符时失败。

我们可以使用dialect解决这个问题

In [7]: dia = csv.excel()

In [8]: dia.quoting = csv.QUOTE_NONE

In [9]: pd.read_csv(StringIO(data), dialect=dia)
Out[9]: 
       label1 label2 label3
index1     "a      c      e
index2      b      d      f

所有的方言选项可以通过关键字参数单独指定:

In [10]: data = 'a,b,c~1,2,3~4,5,6'

In [11]: pd.read_csv(StringIO(data), lineterminator='~')
Out[11]: 
   a  b  c
0  1  2  3
1  4  5  6

另一个常用的方言选项是skipinitialspace,跳过分隔符后的任何空格:

In [12]: data = 'a, b, c\n1, 2, 3\n4, 5, 6'

In [13]: print(data)
a, b, c
1, 2, 3
4, 5, 6

In [14]: pd.read_csv(StringIO(data), skipinitialspace=True)
Out[14]: 
   a  b  c
0  1  2  3
1  4  5  6

解析器每一次尝试“做正确的事情”,而不是非常脆弱。类型推理是一个相当大的交易。因此,如果列可以强制转换为整数dtype,而不改变内容,它将这样做。任何非数字列将通过作为对象dtype与其余的pandas对象。

Specifying column data types

从v0.10开始,可以指定整个DataFrame或单独列的数据类型:

In [15]: data = 'a,b,c\n1,2,3\n4,5,6\n7,8,9'

In [16]: print(data)
a,b,c
1,2,3
4,5,6
7,8,9

In [17]: df = pd.read_csv(StringIO(data), dtype=object)

In [18]: df
Out[18]: 
   a  b  c
0  1  2  3
1  4  5  6
2  7  8  9

In [19]: df['a'][0]
Out[19]: '1'

In [20]: df = pd.read_csv(StringIO(data), dtype={'b': object, 'c': np.float64})

In [21]: df.dtypes
Out[21]: 
a      int64
b     object
c    float64
dtype: object

幸运的是,pandas提供了多种方法来确保您的列只包含一个dtypeIf you’re unfamiliar with these concepts, you can see here to learn more about dtypes, and here to learn more about object conversion in pandas.

例如,您可以使用read_csv()converters参数:

In [22]: data = "col_1\n1\n2\n'A'\n4.22"

In [23]: df = pd.read_csv(StringIO(data), converters={'col_1':str})

In [24]: df
Out[24]: 
  col_1
0     1
1     2
2   'A'
3  4.22

In [25]: df['col_1'].apply(type).value_counts()
Out[25]: 
<type 'str'>    4
Name: col_1, dtype: int64

或者您可以使用to_numeric()函数在读取数据后强制dtypes,

In [26]: df2 = pd.read_csv(StringIO(data))

In [27]: df2['col_1'] = pd.to_numeric(df2['col_1'], errors='coerce')

In [28]: df2
Out[28]: 
   col_1
0   1.00
1   2.00
2    NaN
3   4.22

In [29]: df2['col_1'].apply(type).value_counts()
Out[29]: 
<type 'float'>    4
Name: col_1, dtype: int64

它会将所有有效的解析转换为浮点数,将无效的解析作为NaN

最终,如何处理在包含混合dtypes的列中读取取决于您的具体需求。在上面的情况下,如果你想NaN输出数据异常,则to_numeric()可能是你最好的选择。然而,如果你想要强制所有的数据,不管类型,然后使用read_csv()converters参数肯定是值得尝试。

注意

dtype选项目前仅受C引擎支持。使用engine指定dtype而不是“c”会引发ValueError

注意

在某些情况下,使用包含混合dtypes的列读取异常数据将导致不一致的数据集。如果你依靠pandas推断你的列的dtypes,解析引擎将去推断不同数据块的dtypes,而不是一次性的整个数据集。因此,你可以结束与混合dtypes的列。例如,

In [30]: df = pd.DataFrame({'col_1':range(500000) + ['a', 'b'] + range(500000)})

In [31]: df.to_csv('foo')

In [32]: mixed_df = pd.read_csv('foo')

In [33]: mixed_df['col_1'].apply(type).value_counts()
Out[33]: 
<type 'int'>    737858
<type 'str'>    262144
Name: col_1, dtype: int64

In [34]: mixed_df['col_1'].dtype
Out[34]: dtype('O')

将导致mixed_df对于某些块的块包含int dtype,对于其他块包含str,由于来自数据的混合dty读入。重要的是要注意,整个列将标记objectdtype,用于具有混合dtypes的列。

Specifying Categorical dtype

版本0.19.0中的新功能。

Categorical列可以直接通过指定dtype='category'

In [35]: data = 'col1,col2,col3\na,b,1\na,b,2\nc,d,3'

In [36]: pd.read_csv(StringIO(data))
Out[36]: 
  col1 col2  col3
0    a    b     1
1    a    b     2
2    c    d     3

In [37]: pd.read_csv(StringIO(data)).dtypes
Out[37]: 
col1    object
col2    object
col3     int64
dtype: object

In [38]: pd.read_csv(StringIO(data), dtype='category').dtypes
Out[38]: 
col1    category
col2    category
col3    category
dtype: object

可以使用dict规范将各个列解析为Categorical

In [39]: pd.read_csv(StringIO(data), dtype={'col1': 'category'}).dtypes
Out[39]: 
col1    category
col2      object
col3       int64
dtype: object

注意

结果类别将始终被解析为字符串(对象dtype)。如果类别是数字,则可以使用to_numeric()函数或适当时使用另一个转换器(例如to_datetime())转换类别。

In [40]: df = pd.read_csv(StringIO(data), dtype='category')

In [41]: df.dtypes
Out[41]: 
col1    category
col2    category
col3    category
dtype: object

In [42]: df['col3']
Out[42]: 
0    1
1    2
2    3
Name: col3, dtype: category
Categories (3, object): [1, 2, 3]

In [43]: df['col3'].cat.categories = pd.to_numeric(df['col3'].cat.categories)

In [44]: df['col3']
Out[44]: 
0    1
1    2
2    3
Name: col3, dtype: category
Categories (3, int64): [1, 2, 3]

Naming and Using Columns

Handling column names

文件可以有也可以没有标题行。pandas假设第一行应该用作列名:

In [45]: data = 'a,b,c\n1,2,3\n4,5,6\n7,8,9'

In [46]: print(data)
a,b,c
1,2,3
4,5,6
7,8,9

In [47]: pd.read_csv(StringIO(data))
Out[47]: 
   a  b  c
0  1  2  3
1  4  5  6
2  7  8  9

通过与header结合指定names参数,您可以指示要使用的其他名称以及是否丢弃标题行(如果有):

In [48]: print(data)
a,b,c
1,2,3
4,5,6
7,8,9

In [49]: pd.read_csv(StringIO(data), names=['foo', 'bar', 'baz'], header=0)
Out[49]: 
   foo  bar  baz
0    1    2    3
1    4    5    6
2    7    8    9

In [50]: pd.read_csv(StringIO(data), names=['foo', 'bar', 'baz'], header=None)
Out[50]: 
  foo bar baz
0   a   b   c
1   1   2   3
2   4   5   6
3   7   8   9

如果标题位于第一行以外的行,请将行号传递到header这将跳过前面的行:

In [51]: data = 'skip this skip it\na,b,c\n1,2,3\n4,5,6\n7,8,9'

In [52]: pd.read_csv(StringIO(data), header=1)
Out[52]: 
   a  b  c
0  1  2  3
1  4  5  6
2  7  8  9

Duplicate names parsing

如果文件或标题包含重复的名称,则pandas默认会对这些名称进行重复数据删除,以防止数据覆盖:

In [53]: data = 'a,b,a\n0,1,2\n3,4,5'

In [54]: pd.read_csv(StringIO(data))
Out[54]: 
   a  b  a.1
0  0  1    2
1  3  4    5

没有更多的重复数据,因为默认情况下,mangle_dupe_cols=True会修改一系列重复的列'X'...'X'变成'X.0'...'X.N '。如果mangle_dupe_cols = False,可能会出现重复的数据:

In [2]: data = 'a,b,a\n0,1,2\n3,4,5'
In [3]: pd.read_csv(StringIO(data), mangle_dupe_cols=False)
Out[3]:
   a  b  a
0  2  1  2
1  5  4  5

为了防止用户在重复数据中遇到此问题,如果mangle_dupe_cols != True,则会引发ValueError t5>

In [2]: data = 'a,b,a\n0,1,2\n3,4,5'
In [3]: pd.read_csv(StringIO(data), mangle_dupe_cols=False)
...
ValueError: Setting mangle_dupe_cols=False is not supported yet

Filtering columns (usecols)

usecols参数允许您使用列名称或位置数字选择文件中的任何列子集:

In [55]: data = 'a,b,c,d\n1,2,3,foo\n4,5,6,bar\n7,8,9,baz'

In [56]: pd.read_csv(StringIO(data))
Out[56]: 
   a  b  c    d
0  1  2  3  foo
1  4  5  6  bar
2  7  8  9  baz

In [57]: pd.read_csv(StringIO(data), usecols=['b', 'd'])
Out[57]: 
   b    d
0  2  foo
1  5  bar
2  8  baz

In [58]: pd.read_csv(StringIO(data), usecols=[0, 2, 3])
Out[58]: 
   a  c    d
0  1  3  foo
1  4  6  bar
2  7  9  baz

Comments and Empty Lines

Ignoring line comments and empty lines

如果指定comment参数,则完全注释的行将被忽略。默认情况下,完全空白行也将被忽略。这两个都是版本0.15中引入的API更改。

In [59]: data = '\na,b,c\n  \n# commented line\n1,2,3\n\n4,5,6'

In [60]: print(data)

a,b,c
  
1,2,3

4,5,6

# commented line
In [61]: pd.read_csv(StringIO(data), comment='#')
Out[61]: 
   a  b  c
0  1  2  3
1  4  5  6

如果skip_blank_lines=False,则read_csv将不会忽略空行:

In [62]: data = 'a,b,c\n\n1,2,3\n\n\n4,5,6'

In [63]: pd.read_csv(StringIO(data), skip_blank_lines=False)
Out[63]: 
     a    b    c
0  NaN  NaN  NaN
1  1.0  2.0  3.0
2  NaN  NaN  NaN
3  NaN  NaN  NaN
4  4.0  5.0  6.0

警告

忽略行的存在可能产生涉及行号的模糊性;参数header使用行号(忽略注释/空行),而skiprows使用行号(包括注释/空行):

In [64]: data = '#comment\na,b,c\nA,B,C\n1,2,3'

In [65]: pd.read_csv(StringIO(data), comment='#', header=1)
Out[65]: 
   A  B  C
0  1  2  3

In [66]: data = 'A,B,C\n#comment\na,b,c\n1,2,3'

In [67]: pd.read_csv(StringIO(data), comment='#', skiprows=2)
Out[67]: 
   a  b  c
0  1  2  3

如果指定headerskiprows,则header将相对于skiprows的结尾。例如:

In [68]: data = '# empty\n# second empty line\n# third empty' \

In [68]: 'line\nX,Y,Z\n1,2,3\nA,B,C\n1,2.,4.\n5.,NaN,10.0'

In [69]: print(data)
# empty
# second empty line
# third emptyline
X,Y,Z
1,2,3
A,B,C
1,2.,4.
5.,NaN,10.0

In [70]: pd.read_csv(StringIO(data), comment='#', skiprows=4, header=1)
Out[70]: 
     A    B     C
0  1.0  2.0   4.0
1  5.0  NaN  10.0

Comments

有时评论或元数据可能包含在文件中:

In [71]: print(open('tmp.csv').read())
ID,level,category
Patient1,123000,x # really unpleasant
Patient2,23000,y # wouldn't take his medicine
Patient3,1234018,z # awesome

默认情况下,解析器在输出中包括注释:

In [72]: df = pd.read_csv('tmp.csv')

In [73]: df
Out[73]: 
         ID    level                        category
0  Patient1   123000           x # really unpleasant
1  Patient2    23000  y # wouldn't take his medicine
2  Patient3  1234018                     z # awesome

我们可以使用comment关键字取消注释:

In [74]: df = pd.read_csv('tmp.csv', comment='#')

In [75]: df
Out[75]: 
         ID    level category
0  Patient1   123000       x 
1  Patient2    23000       y 
2  Patient3  1234018       z 

Dealing with Unicode Data

对于编码的unicode数据,应使用encoding参数,这将导致在结果中将字节字符串解码为unicode:

In [76]: data = b'word,length\nTr\xc3\xa4umen,7\nGr\xc3\xbc\xc3\x9fe,5'.decode('utf8').encode('latin-1')

In [77]: df = pd.read_csv(BytesIO(data), encoding='latin-1')

In [78]: df
Out[78]: 
      word  length
0  Träumen       7
1    Grüße       5

In [79]: df['word'][1]
Out[79]: u'Gr\xfc\xdfe'

一些将所有字符编码为多个字节(如UTF-16)的格式将不会正确解析,而不指定编码。Python标准编码的完整列表

Index columns and trailing delimiters

如果一个文件还有一列数据而不是列名数,则第一列将被用作DataFrame的行名称:

In [80]: data = 'a,b,c\n4,apple,bat,5.7\n8,orange,cow,10'

In [81]: pd.read_csv(StringIO(data))
Out[81]: 
        a    b     c
4   apple  bat   5.7
8  orange  cow  10.0
In [82]: data = 'index,a,b,c\n4,apple,bat,5.7\n8,orange,cow,10'

In [83]: pd.read_csv(StringIO(data), index_col=0)
Out[83]: 
            a    b     c
index                   
4       apple  bat   5.7
8      orange  cow  10.0

通常,您可以使用index_col选项来实现此行为。

当在每个数据行的末尾使用定界符准备文件时,会出现一些异常情况,从而导致解析器混乱。要显式禁用索引列推断并放弃最后一列,请传递index_col=False

In [84]: data = 'a,b,c\n4,apple,bat,\n8,orange,cow,'

In [85]: print(data)
a,b,c
4,apple,bat,
8,orange,cow,

In [86]: pd.read_csv(StringIO(data))
Out[86]: 
        a    b   c
4   apple  bat NaN
8  orange  cow NaN

In [87]: pd.read_csv(StringIO(data), index_col=False)
Out[87]: 
   a       b    c
0  4   apple  bat
1  8  orange  cow

Date Handling

Specifying Date Columns

为了更好地使用datetime数据,read_csv()read_table()使用关键字参数parse_datesdate_parser以允许用户指定各种列和日期/时间格式将输入文本数据转换为datetime对象。

最简单的情况是传入parse_dates=True

# Use a column as an index, and parse it as dates.
In [88]: df = pd.read_csv('foo.csv', index_col=0, parse_dates=True)

In [89]: df
Out[89]: 
            A  B  C
date               
2009-01-01  a  1  2
2009-01-02  b  3  4
2009-01-03  c  4  5

# These are python datetime objects
In [90]: df.index
Out[90]: DatetimeIndex(['2009-01-01', '2009-01-02', '2009-01-03'], dtype='datetime64[ns]', name=u'date', freq=None)

通常情况下,我们可能要分开存储日期和时间数据,或单独存储各种日期字段。parse_dates关键字可用于指定解析日期和/或时间的列的组合。

您可以将列列表指定为parse_dates,生成的日期列将预置到输出(以不影响现有列顺序),新的列名称将是组件列名称:

In [91]: print(open('tmp.csv').read())
KORD,19990127, 19:00:00, 18:56:00, 0.8100
KORD,19990127, 20:00:00, 19:56:00, 0.0100
KORD,19990127, 21:00:00, 20:56:00, -0.5900
KORD,19990127, 21:00:00, 21:18:00, -0.9900
KORD,19990127, 22:00:00, 21:56:00, -0.5900
KORD,19990127, 23:00:00, 22:56:00, -0.5900

In [92]: df = pd.read_csv('tmp.csv', header=None, parse_dates=[[1, 2], [1, 3]])

In [93]: df
Out[93]: 
                  1_2                 1_3     0     4
0 1999-01-27 19:00:00 1999-01-27 18:56:00  KORD  0.81
1 1999-01-27 20:00:00 1999-01-27 19:56:00  KORD  0.01
2 1999-01-27 21:00:00 1999-01-27 20:56:00  KORD -0.59
3 1999-01-27 21:00:00 1999-01-27 21:18:00  KORD -0.99
4 1999-01-27 22:00:00 1999-01-27 21:56:00  KORD -0.59
5 1999-01-27 23:00:00 1999-01-27 22:56:00  KORD -0.59

默认情况下,解析器会删除组件日期列,但您可以选择通过keep_date_col关键字保留它们:

In [94]: df = pd.read_csv('tmp.csv', header=None, parse_dates=[[1, 2], [1, 3]],
   ....:                  keep_date_col=True)
   ....: 

In [95]: df
Out[95]: 
                  1_2                 1_3     0         1          2  \
0 1999-01-27 19:00:00 1999-01-27 18:56:00  KORD  19990127   19:00:00   
1 1999-01-27 20:00:00 1999-01-27 19:56:00  KORD  19990127   20:00:00   
2 1999-01-27 21:00:00 1999-01-27 20:56:00  KORD  19990127   21:00:00   
3 1999-01-27 21:00:00 1999-01-27 21:18:00  KORD  19990127   21:00:00   
4 1999-01-27 22:00:00 1999-01-27 21:56:00  KORD  19990127   22:00:00   
5 1999-01-27 23:00:00 1999-01-27 22:56:00  KORD  19990127   23:00:00   

           3     4  
0   18:56:00  0.81  
1   19:56:00  0.01  
2   20:56:00 -0.59  
3   21:18:00 -0.99  
4   21:56:00 -0.59  
5   22:56:00 -0.59  

请注意,如果您希望将多个列合并到单个日期列中,则必须使用嵌套列表。In other words, parse_dates=[1, 2] indicates that the second and third columns should each be parsed as separate date columns while parse_dates=[[1, 2]] means the two columns should be parsed into a single column.

您还可以使用dict指定自定义名称列:

In [96]: date_spec = {'nominal': [1, 2], 'actual': [1, 3]}

In [97]: df = pd.read_csv('tmp.csv', header=None, parse_dates=date_spec)

In [98]: df
Out[98]: 
              nominal              actual     0     4
0 1999-01-27 19:00:00 1999-01-27 18:56:00  KORD  0.81
1 1999-01-27 20:00:00 1999-01-27 19:56:00  KORD  0.01
2 1999-01-27 21:00:00 1999-01-27 20:56:00  KORD -0.59
3 1999-01-27 21:00:00 1999-01-27 21:18:00  KORD -0.99
4 1999-01-27 22:00:00 1999-01-27 21:56:00  KORD -0.59
5 1999-01-27 23:00:00 1999-01-27 22:56:00  KORD -0.59

重要的是要记住,如果要将多个文本列解析为单个日期列,则会在数据前面添加一个新列。index_col规范基于此新的列集合,而不是原始数据列:

In [99]: date_spec = {'nominal': [1, 2], 'actual': [1, 3]}

In [100]: df = pd.read_csv('tmp.csv', header=None, parse_dates=date_spec,
   .....:                  index_col=0) #index is the nominal column
   .....: 

In [101]: df
Out[101]: 
                                 actual     0     4
nominal                                            
1999-01-27 19:00:00 1999-01-27 18:56:00  KORD  0.81
1999-01-27 20:00:00 1999-01-27 19:56:00  KORD  0.01
1999-01-27 21:00:00 1999-01-27 20:56:00  KORD -0.59
1999-01-27 21:00:00 1999-01-27 21:18:00  KORD -0.99
1999-01-27 22:00:00 1999-01-27 21:56:00  KORD -0.59
1999-01-27 23:00:00 1999-01-27 22:56:00  KORD -0.59

注意

read_csv有一个fast_path用于解析iso8601格式的日期时间字符串,例如“2000-01-01T00:01:02 + 00:00”和类似的变体。如果您可以安排您的数据以此格式存储数据时间,加载时间将显着更快,观察到约20倍。

注意

当传递一个dict作为parse_dates参数时,不保证前置列的顺序,因为dict对象不对它们的键施加排序。在Python 2.7+上,如果这对你很重要,你可以使用collections.OrderedDict而不是普通的dict因此,当对于'parse_dates'与index_col参数结合使用dict时,最好将index_col指定为列标签,而不是作为结果的索引帧。

Date Parsing Functions

最后,解析器允许您指定自定义date_parser函数,以充分利用日期解析API的灵活性:

In [102]: import pandas.io.date_converters as conv

In [103]: df = pd.read_csv('tmp.csv', header=None, parse_dates=date_spec,
   .....:                  date_parser=conv.parse_date_time)
   .....: 

In [104]: df
Out[104]: 
              nominal              actual     0     4
0 1999-01-27 19:00:00 1999-01-27 18:56:00  KORD  0.81
1 1999-01-27 20:00:00 1999-01-27 19:56:00  KORD  0.01
2 1999-01-27 21:00:00 1999-01-27 20:56:00  KORD -0.59
3 1999-01-27 21:00:00 1999-01-27 21:18:00  KORD -0.99
4 1999-01-27 22:00:00 1999-01-27 21:56:00  KORD -0.59
5 1999-01-27 23:00:00 1999-01-27 22:56:00  KORD -0.59

Pandas将尝试以三种不同的方式调用date_parser函数。如果引发异常,则尝试下一个异常:

  1. 首先使用parse_dates(例如,date_parser(['2013',])定义一个或多个数组作为参数调用date_parser '2013'], ['1', '2'])
  2. 如果#1失败,则调用date_parser,所有列按行连接到单个数组中(例如,date_parser(['2013 1' , '2013 2'])
  3. 如果#2失败,则对于具有来自parse_dates指示的列中的一个或多个字符串参数的每一行调用date_parser一次(例如,date_parser 2013“,” '2')的第一行(2013', '1') 用于第二个,等等)

注意,在性能方面,你应该尝试这些方法按顺序解析日期:

  1. 尝试使用infer_datetime_format=True(请参见下面部分)推断格式
  2. 如果您知道格式,请使用pd.to_datetime()date_parser = lambda x: pd.to_datetime , format = ...)
  3. 如果您有非标准格式,请使用自定义date_parser函数。为了获得最佳性能,这应该是向量化的,即它应该接受数组作为参数。

您可以在date_converters.py中探索日期解析功能,并添加自己的日期解析功能。我们希望将这个模块变成一个社区支持的日期/时间解析器集合。为了让您入门,date_converters.py包含用于解析双日期和时间列,年/月/日列和年/月/日/小时/分/秒列的功能。它还包含一个generic_parser函数,因此您可以使用处理单个日期而不是整个数组的函数来对其进行curry。

Inferring Datetime Format

如果您为某些或所有列启用了parse_dates,并且datetime字符串都采用相同的格式,则可以通过设置infer_datetime_format=True如果设置,pandas将尝试猜测datetime字符串的格式,然后使用更快的方式解析字符串。观察到5-10x解析速度。pandas将回退到通常的解析,如果格式不能猜到或者猜测的格式不能正确解析整个字符串列。因此,一般来说,如果启用infer_datetime_format,则不应产生任何负面结果。

以下是可以猜测的日期时间字符串的一些示例(全部表示2011年12月30日00:00:00)

  • “20111230”
  • “2011/12/30”
  • “20111230 00:00:00”
  • “12/30/2011 00:00:00”
  • “30 / Dec / 2011 00:00:00”
  • “30 / December / 2011 00:00:00”

infer_datetime_formatdayfirst敏感。使用dayfirst=True,它会猜到“01/12/2011”为12月1日。使用dayfirst=False(默认),它会猜到“01/12/2011”为1月12日。

# Try to infer the format for the index column
In [105]: df = pd.read_csv('foo.csv', index_col=0, parse_dates=True,
   .....:                  infer_datetime_format=True)
   .....: 

In [106]: df
Out[106]: 
            A  B  C
date               
2009-01-01  a  1  2
2009-01-02  b  3  4
2009-01-03  c  4  5

International Date Formats

虽然美国日期格式通常为MM / DD / YYYY,但许多国际格式使用DD / MM / YYYY。为方便起见,提供了dayfirst关键字:

In [107]: print(open('tmp.csv').read())
date,value,cat
1/6/2000,5,a
2/6/2000,10,b
3/6/2000,15,c

In [108]: pd.read_csv('tmp.csv', parse_dates=[0])
Out[108]: 
        date  value cat
0 2000-01-06      5   a
1 2000-02-06     10   b
2 2000-03-06     15   c

In [109]: pd.read_csv('tmp.csv', dayfirst=True, parse_dates=[0])
Out[109]: 
        date  value cat
0 2000-06-01      5   a
1 2000-06-02     10   b
2 2000-06-03     15   c

Specifying method for floating-point conversion

可以指定参数float_precision,以便在使用C引擎进行解析期间使用特定的浮点转换器。选项是普通转换器,高精度转换器和往返转换器(在写入文件后保证往返值)。例如:

In [110]: val = '0.3066101993807095471566981359501369297504425048828125'

In [111]: data = 'a,b,c\n1,2,{0}'.format(val)

In [112]: abs(pd.read_csv(StringIO(data), engine='c', float_precision=None)['c'][0] - float(val))
Out[112]: 1.1102230246251565e-16

In [113]: abs(pd.read_csv(StringIO(data), engine='c', float_precision='high')['c'][0] - float(val))
Out[113]: 5.5511151231257827e-17

In [114]: abs(pd.read_csv(StringIO(data), engine='c', float_precision='round_trip')['c'][0] - float(val))
Out[114]: 0.0

Thousand Separators

对于已使用千位分隔符写入的大数字,可以将thousands关键字设置为长度为1的字符串,以便整数将被正确解析:

默认情况下,带有千位分隔符的数字将被解析为字符串

In [115]: print(open('tmp.csv').read())
ID|level|category
Patient1|123,000|x
Patient2|23,000|y
Patient3|1,234,018|z

In [116]: df = pd.read_csv('tmp.csv', sep='|')

In [117]: df
Out[117]: 
         ID      level category
0  Patient1    123,000        x
1  Patient2     23,000        y
2  Patient3  1,234,018        z

In [118]: df.level.dtype
Out[118]: dtype('O')

thousands关键字允许正确解析整数

In [119]: print(open('tmp.csv').read())
ID|level|category
Patient1|123,000|x
Patient2|23,000|y
Patient3|1,234,018|z

In [120]: df = pd.read_csv('tmp.csv', sep='|', thousands=',')

In [121]: df
Out[121]: 
         ID    level category
0  Patient1   123000        x
1  Patient2    23000        y
2  Patient3  1234018        z

In [122]: df.level.dtype
Out[122]: dtype('int64')

NA Values

要控制哪些值被解析为缺失值(由NaN表示),请在na_values中指定一个字符串。如果指定字符串列表,则其中的所有值都将被视为缺少值。如果您指定一个数字(float,例如5.0integer,例如5),也将意味着缺失值(在这种情况下,有效地[5.0,5]被识别为NaN

要完全覆盖被识别为缺少的默认值,请指定keep_default_na=FalseThe default NaN recognized values are ['-1.#IND', '1.#QNAN', '1.#IND', '-1.#QNAN', '#N/A','N/A', 'NA', '#NA', 'NULL', 'NaN', '-NaN', 'nan', '-nan']. 虽然长度为0的字符串''不包含在默认的NaN值列表中,但仍被视为缺失值。

read_csv(path, na_values=[5])

55.0被解释为数字被识别为NaN

read_csv(path, keep_default_na=False, na_values=[""])

只有空字段为NaN

read_csv(path, keep_default_na=False, na_values=["NA", "0"])

只有NA0作为字符串是NaN

read_csv(path, na_values=["Nope"])

字符串"Nope"被识别为NaN

Infinity

inf的值将被解析为np.inf(正无穷大),-inf-np.inf这些将忽略该值的情况,意思是Inf,也将被解析为np.inf

Returning Series

使用squeeze关键字,解析器将返回单个列作为Series的输出:

In [123]: print(open('tmp.csv').read())
level
Patient1,123000
Patient2,23000
Patient3,1234018

In [124]: output =  pd.read_csv('tmp.csv', squeeze=True)

In [125]: output
Out[125]: 
Patient1     123000
Patient2      23000
Patient3    1234018
Name: level, dtype: int64

In [126]: type(output)
Out[126]: pandas.core.series.Series

Boolean values

公共值TrueFalseTRUEFALSE都被识别为布尔值。有时你想要识别一些其他值为布尔。为此,请使用true_valuesfalse_values选项:

In [127]: data= 'a,b,c\n1,Yes,2\n3,No,4'

In [128]: print(data)
a,b,c
1,Yes,2
3,No,4

In [129]: pd.read_csv(StringIO(data))
Out[129]: 
   a    b  c
0  1  Yes  2
1  3   No  4

In [130]: pd.read_csv(StringIO(data), true_values=['Yes'], false_values=['No'])
Out[130]: 
   a      b  c
0  1   True  2
1  3  False  4

Handling “bad” lines

某些文件可能包含字段太少或太多的格式不正确的行。具有太少字段的行将在尾部字段中填充NA值。过多的行会默认产生错误:

In [27]: data = 'a,b,c\n1,2,3\n4,5,6,7\n8,9,10'

In [28]: pd.read_csv(StringIO(data))
---------------------------------------------------------------------------
CParserError                              Traceback (most recent call last)
CParserError: Error tokenizing data. C error: Expected 3 fields in line 3, saw 4

你可以选择跳过坏行:

In [29]: pd.read_csv(StringIO(data), error_bad_lines=False)
Skipping line 3: expected 3 fields, saw 4

Out[29]:
   a  b   c
0  1  2   3
1  8  9  10

Quoting and Escape Characters

嵌入字段中的引号(和其他转义字符)可以以任何数量的方式处理。一种方法是使用反斜杠;要正确解析此数据,您应该传递escapechar选项:

In [131]: data = 'a,b\n"hello, \\"Bob\\", nice to see you",5'

In [132]: print(data)
a,b
"hello, \"Bob\", nice to see you",5

In [133]: pd.read_csv(StringIO(data), escapechar='\\')
Out[133]: 
                               a  b
0  hello, "Bob", nice to see you  5

Files with Fixed Width Columns

read_csv读取定界数据时,read_fwf()函数适用于已知和固定列宽的数据文件。read_fwf的函数参数与具有两个额外参数的read_csv大致相同:

  • colspecs:将每行的固定宽度字段的范围作为半开间隔(即,从[from,to])的对(元组)列表。字符串值“infer”可以用于指示解析器尝试从数据的前100行中检测列规范。默认行为,如果没有指定,是推断。
  • widths:如果间隔是连续的,可以使用字段宽度列表来代替“colspecs”。

考虑一个典型的固定宽度数据文件:

In [134]: print(open('bar.csv').read())
id8141    360.242940   149.910199   11950.7
id1594    444.953632   166.985655   11788.4
id1849    364.136849   183.628767   11806.2
id1230    413.836124   184.375703   11916.8
id1948    502.953953   173.237159   12468.3

为了将该文件解析为DataFrame,我们只需要向read_fwf函数提供列规范以及文件名:

#Column specifications are a list of half-intervals
In [135]: colspecs = [(0, 6), (8, 20), (21, 33), (34, 43)]

In [136]: df = pd.read_fwf('bar.csv', colspecs=colspecs, header=None, index_col=0)

In [137]: df
Out[137]: 
                 1           2        3
0                                      
id8141  360.242940  149.910199  11950.7
id1594  444.953632  166.985655  11788.4
id1849  364.136849  183.628767  11806.2
id1230  413.836124  184.375703  11916.8
id1948  502.953953  173.237159  12468.3

注意解析器如何自动选择列名X.当指定header=None参数时,或者,您可以只提供连续列的列宽:

#Widths are a list of integers
In [138]: widths = [6, 14, 13, 10]

In [139]: df = pd.read_fwf('bar.csv', widths=widths, header=None)

In [140]: df
Out[140]: 
        0           1           2        3
0  id8141  360.242940  149.910199  11950.7
1  id1594  444.953632  166.985655  11788.4
2  id1849  364.136849  183.628767  11806.2
3  id1230  413.836124  184.375703  11916.8
4  id1948  502.953953  173.237159  12468.3

解析器将处理列周围的额外的空白空间,因此在文件中的列之间可以有额外的分隔。

版本0.13.0中的新功能。

默认情况下,read_fwf会尝试使用文件的前100行来推断文件的colspecs它只能在列对齐并通过提供的delimiter(默认分隔符为空格)正确分隔的情况下才能执行。

In [141]: df = pd.read_fwf('bar.csv', header=None, index_col=0)

In [142]: df
Out[142]: 
                 1           2        3
0                                      
id8141  360.242940  149.910199  11950.7
id1594  444.953632  166.985655  11788.4
id1849  364.136849  183.628767  11806.2
id1230  413.836124  184.375703  11916.8
id1948  502.953953  173.237159  12468.3

Indexes

Files with an “implicit” index column

考虑一个文件在头中少于一个数据列数:

In [143]: print(open('foo.csv').read())
A,B,C
20090101,a,1,2
20090102,b,3,4
20090103,c,4,5

在这种特殊情况下,read_csv假定第一列将用作DataFrame的索引:

In [144]: pd.read_csv('foo.csv')
Out[144]: 
          A  B  C
20090101  a  1  2
20090102  b  3  4
20090103  c  4  5

请注意,日期不会自动解析。在这种情况下,你需要像以前一样做:

In [145]: df = pd.read_csv('foo.csv', parse_dates=True)

In [146]: df.index
Out[146]: DatetimeIndex(['2009-01-01', '2009-01-02', '2009-01-03'], dtype='datetime64[ns]', freq=None)

Reading an index with a MultiIndex

假设您的数据由两列索引:

In [147]: print(open('data/mindex_ex.csv').read())
year,indiv,zit,xit
1977,"A",1.2,.6
1977,"B",1.5,.5
1977,"C",1.7,.8
1978,"A",.2,.06
1978,"B",.7,.2
1978,"C",.8,.3
1978,"D",.9,.5
1978,"E",1.4,.9
1979,"C",.2,.15
1979,"D",.14,.05
1979,"E",.5,.15
1979,"F",1.2,.5
1979,"G",3.4,1.9
1979,"H",5.4,2.7
1979,"I",6.4,1.2

read_csvread_tableindex_col参数可以使用列号列表将多个列转换为MultiIndex返回对象的索引:

In [148]: df = pd.read_csv("data/mindex_ex.csv", index_col=[0,1])

In [149]: df
Out[149]: 
             zit   xit
year indiv            
1977 A      1.20  0.60
     B      1.50  0.50
     C      1.70  0.80
1978 A      0.20  0.06
     B      0.70  0.20
     C      0.80  0.30
     D      0.90  0.50
     E      1.40  0.90
1979 C      0.20  0.15
     D      0.14  0.05
     E      0.50  0.15
     F      1.20  0.50
     G      3.40  1.90
     H      5.40  2.70
     I      6.40  1.20

In [150]: df.ix[1978]
Out[150]: 
       zit   xit
indiv           
A      0.2  0.06
B      0.7  0.20
C      0.8  0.30
D      0.9  0.50
E      1.4  0.90

Reading columns with a MultiIndex

通过指定header参数的行位置列表,您可以在MultiIndex中读取列。指定非连续行将跳过中间行。为了具有tingleizing列的pre-0.13行为,请指定tupleize_cols=True

In [151]: from pandas.util.testing import makeCustomDataframe as mkdf

In [152]: df = mkdf(5,3,r_idx_nlevels=2,c_idx_nlevels=4)

In [153]: df.to_csv('mi.csv')

In [154]: print(open('mi.csv').read())
C0,,C_l0_g0,C_l0_g1,C_l0_g2
C1,,C_l1_g0,C_l1_g1,C_l1_g2
C2,,C_l2_g0,C_l2_g1,C_l2_g2
C3,,C_l3_g0,C_l3_g1,C_l3_g2
R0,R1,,,
R_l0_g0,R_l1_g0,R0C0,R0C1,R0C2
R_l0_g1,R_l1_g1,R1C0,R1C1,R1C2
R_l0_g2,R_l1_g2,R2C0,R2C1,R2C2
R_l0_g3,R_l1_g3,R3C0,R3C1,R3C2
R_l0_g4,R_l1_g4,R4C0,R4C1,R4C2


In [155]: pd.read_csv('mi.csv',header=[0,1,2,3],index_col=[0,1])
Out[155]: 
C0              C_l0_g0 C_l0_g1 C_l0_g2
C1              C_l1_g0 C_l1_g1 C_l1_g2
C2              C_l2_g0 C_l2_g1 C_l2_g2
C3              C_l3_g0 C_l3_g1 C_l3_g2
R0      R1                             
R_l0_g0 R_l1_g0    R0C0    R0C1    R0C2
R_l0_g1 R_l1_g1    R1C0    R1C1    R1C2
R_l0_g2 R_l1_g2    R2C0    R2C1    R2C2
R_l0_g3 R_l1_g3    R3C0    R3C1    R3C2
R_l0_g4 R_l1_g4    R4C0    R4C1    R4C2

从0.13.0开始,read_csv将能够解释更常见的多列索引格式。

In [156]: print(open('mi2.csv').read())
,a,a,a,b,c,c
,q,r,s,t,u,v
one,1,2,3,4,5,6
two,7,8,9,10,11,12

In [157]: pd.read_csv('mi2.csv',header=[0,1],index_col=0)
Out[157]: 
     a         b   c    
     q  r  s   t   u   v
one  1  2  3   4   5   6
two  7  8  9  10  11  12

Note: If an index_col is not specified (e.g. you don’t have an index, or wrote it with df.to_csv(..., index=False), then any names on the columns index will be lost.

Automatically “sniffing” the delimiter

read_csv能够推断定界(不一定是逗号分隔)文件,因为pandas使用csv模块的csv.Sniffer类。为此,您必须指定sep=None

In [158]: print(open('tmp2.sv').read())
:0:1:2:3
0:0.469112299907:-0.282863344329:-1.50905850317:-1.13563237102
1:1.21211202502:-0.173214649053:0.119208711297:-1.04423596628
2:-0.861848963348:-2.10456921889:-0.494929274069:1.07180380704
3:0.721555162244:-0.70677113363:-1.03957498511:0.271859885543
4:-0.424972329789:0.567020349794:0.276232019278:-1.08740069129
5:-0.673689708088:0.113648409689:-1.47842655244:0.524987667115
6:0.40470521868:0.57704598592:-1.71500201611:-1.03926848351
7:-0.370646858236:-1.15789225064:-1.34431181273:0.844885141425
8:1.07576978372:-0.10904997528:1.64356307036:-1.46938795954
9:0.357020564133:-0.67460010373:-1.77690371697:-0.968913812447


In [159]: pd.read_csv('tmp2.sv', sep=None, engine='python')
Out[159]: 
   Unnamed: 0         0         1         2         3
0           0  0.469112 -0.282863 -1.509059 -1.135632
1           1  1.212112 -0.173215  0.119209 -1.044236
2           2 -0.861849 -2.104569 -0.494929  1.071804
3           3  0.721555 -0.706771 -1.039575  0.271860
4           4 -0.424972  0.567020  0.276232 -1.087401
5           5 -0.673690  0.113648 -1.478427  0.524988
6           6  0.404705  0.577046 -1.715002 -1.039268
7           7 -0.370647 -1.157892 -1.344312  0.844885
8           8  1.075770 -0.109050  1.643563 -1.469388
9           9  0.357021 -0.674600 -1.776904 -0.968914

Iterating through files chunk by chunk

假设您希望延迟遍历一个(可能非常大)的文件,而不是将整个文件读入内存,如下所示:

In [160]: print(open('tmp.sv').read())
|0|1|2|3
0|0.469112299907|-0.282863344329|-1.50905850317|-1.13563237102
1|1.21211202502|-0.173214649053|0.119208711297|-1.04423596628
2|-0.861848963348|-2.10456921889|-0.494929274069|1.07180380704
3|0.721555162244|-0.70677113363|-1.03957498511|0.271859885543
4|-0.424972329789|0.567020349794|0.276232019278|-1.08740069129
5|-0.673689708088|0.113648409689|-1.47842655244|0.524987667115
6|0.40470521868|0.57704598592|-1.71500201611|-1.03926848351
7|-0.370646858236|-1.15789225064|-1.34431181273|0.844885141425
8|1.07576978372|-0.10904997528|1.64356307036|-1.46938795954
9|0.357020564133|-0.67460010373|-1.77690371697|-0.968913812447


In [161]: table = pd.read_table('tmp.sv', sep='|')

In [162]: table
Out[162]: 
   Unnamed: 0         0         1         2         3
0           0  0.469112 -0.282863 -1.509059 -1.135632
1           1  1.212112 -0.173215  0.119209 -1.044236
2           2 -0.861849 -2.104569 -0.494929  1.071804
3           3  0.721555 -0.706771 -1.039575  0.271860
4           4 -0.424972  0.567020  0.276232 -1.087401
5           5 -0.673690  0.113648 -1.478427  0.524988
6           6  0.404705  0.577046 -1.715002 -1.039268
7           7 -0.370647 -1.157892 -1.344312  0.844885
8           8  1.075770 -0.109050  1.643563 -1.469388
9           9  0.357021 -0.674600 -1.776904 -0.968914

通过指定chunksizeread_csvread_table,返回值将是TextFileReader类型的可迭代对象:

In [163]: reader = pd.read_table('tmp.sv', sep='|', chunksize=4)

In [164]: reader
Out[164]: <pandas.io.parsers.TextFileReader at 0x7ff27e15a450>

In [165]: for chunk in reader:
   .....:     print(chunk)
   .....: 
   Unnamed: 0         0         1         2         3
0           0  0.469112 -0.282863 -1.509059 -1.135632
1           1  1.212112 -0.173215  0.119209 -1.044236
2           2 -0.861849 -2.104569 -0.494929  1.071804
3           3  0.721555 -0.706771 -1.039575  0.271860
   Unnamed: 0         0         1         2         3
4           4 -0.424972  0.567020  0.276232 -1.087401
5           5 -0.673690  0.113648 -1.478427  0.524988
6           6  0.404705  0.577046 -1.715002 -1.039268
7           7 -0.370647 -1.157892 -1.344312  0.844885
   Unnamed: 0         0        1         2         3
8           8  1.075770 -0.10905  1.643563 -1.469388
9           9  0.357021 -0.67460 -1.776904 -0.968914

指定iterator=True也会返回TextFileReader对象:

In [166]: reader = pd.read_table('tmp.sv', sep='|', iterator=True)

In [167]: reader.get_chunk(5)
Out[167]: 
   Unnamed: 0         0         1         2         3
0           0  0.469112 -0.282863 -1.509059 -1.135632
1           1  1.212112 -0.173215  0.119209 -1.044236
2           2 -0.861849 -2.104569 -0.494929  1.071804
3           3  0.721555 -0.706771 -1.039575  0.271860
4           4 -0.424972  0.567020  0.276232 -1.087401

Specifying the parser engine

引擎下pandas使用一个快速和高效的解析器实现在C以及一个python实现,目前更功能完整。在可能的情况下,pandas使用C解析器(指定为engine='c'),但如果指定了C不支持的选项,则可能会回到python。目前,C不受支持的选项包括:

指定以上任何选项将产生ParserWarning,除非使用engine='python'明确选择了python引擎。

Writing out Data

Writing to CSV format

Series和DataFrame对象具有一个实例方法to_csv,它允许将对象的内容存储为逗号分隔值文件。该函数接受一些参数。只有第一个是必需的。

  • path_or_buf:要写入的文件或StringIO的字符串路径
  • sep:输出文件的字段分隔符(默认为“,”)
  • na_rep:缺少值的字符串表示形式(默认为'')
  • float_format:格式化浮点数字符串
  • cols:要写入的列(默认值为无)
  • header:是否写出列名(默认为True)
  • index:是否写入行(索引)名称(默认为True)
  • index_label:索引列的列标签(如果需要)。如果无(默认),index为True,则使用索引名称。(如果DataFrame使用MultiIndex,应该给出一个序列)。
  • mode:Python写模式,默认为'w'
  • encoding:表示要使用的编码的字符串,如果内容是非ASCII的,对于python版本3之前
  • line_terminator:表示行结束的字符序列(默认'\ n')
  • quoting:在csv模块中设置引用规则(默认为csv.QUOTE_MINIMAL)。注意,如果你设置了一个float_format,那么浮点数被转换为字符串,csv.QUOTE_NONNUMERIC会将它们作为非数字
  • quotechar:用于引用字段的字符(默认'“')
  • doublequote:在字段中控制quotechar的引用(默认值为True)
  • escapechar:适当时用于转义sepquotechar的字符(默认值为None)
  • chunksize:每次写入的行数
  • tupleize_cols:如果为False(默认值),则写为元组列表,否则以适用于read_csv
  • date_format:格式化datetime对象的字符串

Writing a formatted string

DataFrame对象有一个实例方法to_string,它允许控制对象的字符串表示。所有参数都是可选的:

  • buf默认值无,例如StringIO对象
  • columns默认值无,要写入的列
  • col_space默认值无,每列的最小宽度。
  • na_rep默认NaN,表示NA值
  • formatters default无,函数的字典(按列),每个函数接受单个参数并返回格式化的字符串
  • float_format default无,一个函数,它接受一个(float)参数并返回一个格式化的字符串;以应用于DataFrame中的浮动。
  • sparsify default True,对于具有层次索引的DataFrame,设置为False以在每行打印每个多索引键。
  • index_names默认为True,将打印索引的名称
  • index default True,将打印索引(即行标签)
  • header default True,将打印列标签
  • justify默认left,将左对齐或右对齐打印列标题

Series对象还有一个to_string方法,但只有bufna_repfloat_format参数。还有一个length参数,如果设置为True,将另外输出系列的长度。

JSON

读取和写入JSON格式的文件和字符串。

Writing JSON

可以将SeriesDataFrame转换为有效的JSON字符串。使用可选参数to_json

Note NaN‘s, NaT‘s and None will be converted to null and datetime objects will be converted based on the date_format and date_unit parameters.

In [168]: dfj = pd.DataFrame(randn(5, 2), columns=list('AB'))

In [169]: json = dfj.to_json()

In [170]: json
Out[170]: '{"A":{"0":-1.2945235903,"1":0.2766617129,"2":-0.0139597524,"3":-0.0061535699,"4":0.8957173022},"B":{"0":0.4137381054,"1":-0.472034511,"2":-0.3625429925,"3":-0.923060654,"4":0.8052440254}}'

Orient Options

生成的JSON文件/字符串的格式有多种不同的选项。考虑下面的DataFrame和Series:

In [171]: dfjo = pd.DataFrame(dict(A=range(1, 4), B=range(4, 7), C=range(7, 10)),
   .....:                     columns=list('ABC'), index=list('xyz'))
   .....: 

In [172]: dfjo
Out[172]: 
   A  B  C
x  1  4  7
y  2  5  8
z  3  6  9

In [173]: sjo = pd.Series(dict(x=15, y=16, z=17), name='D')

In [174]: sjo
Out[174]: 
x    15
y    16
z    17
Name: D, dtype: int64

面向列DataFrame的默认值)将数据序列化为以列标签作为主索引的嵌套JSON对象:

In [175]: dfjo.to_json(orient="columns")
Out[175]: '{"A":{"x":1,"y":2,"z":3},"B":{"x":4,"y":5,"z":6},"C":{"x":7,"y":8,"z":9}}'

面向索引(类似于Series的默认值)类似于面向列,但索引标签现在是主要的:

In [176]: dfjo.to_json(orient="index")
Out[176]: '{"x":{"A":1,"B":4,"C":7},"y":{"A":2,"B":5,"C":8},"z":{"A":3,"B":6,"C":9}}'

In [177]: sjo.to_json(orient="index")
Out[177]: '{"x":15,"y":16,"z":17}'

面向记录将数据序列化为列 - >值记录的JSON数组,不包括索引标签。这对于将DataFrame数据传递到绘图库很有用,例如JavaScript库d3.js:

In [178]: dfjo.to_json(orient="records")
Out[178]: '[{"A":1,"B":4,"C":7},{"A":2,"B":5,"C":8},{"A":3,"B":6,"C":9}]'

In [179]: sjo.to_json(orient="records")
Out[179]: '[15,16,17]'

面向价值是一个裸体选项,仅序列化为嵌套JSON数组的值,不包括列和索引标签:

In [180]: dfjo.to_json(orient="values")
Out[180]: '[[1,4,7],[2,5,8],[3,6,9]]'

面向分组序列化为包含值,索引和列的单独条目的JSON对象。Series也包括名称:

In [181]: dfjo.to_json(orient="split")
Out[181]: '{"columns":["A","B","C"],"index":["x","y","z"],"data":[[1,4,7],[2,5,8],[3,6,9]]}'

In [182]: sjo.to_json(orient="split")
Out[182]: '{"name":"D","index":["x","y","z"],"data":[15,16,17]}'

注意

编码到JSON对象的任何orient选项将不会在往返序列化期间保留索引和列标签的顺序。如果您希望保留标签排序,请使用拆分选项,因为它使用有序容器。

Date Handling

以ISO日期格式写入

In [183]: dfd = pd.DataFrame(randn(5, 2), columns=list('AB'))

In [184]: dfd['date'] = pd.Timestamp('20130101')

In [185]: dfd = dfd.sort_index(1, ascending=False)

In [186]: json = dfd.to_json(date_format='iso')

In [187]: json
Out[187]: '{"date":{"0":"2013-01-01T00:00:00.000Z","1":"2013-01-01T00:00:00.000Z","2":"2013-01-01T00:00:00.000Z","3":"2013-01-01T00:00:00.000Z","4":"2013-01-01T00:00:00.000Z"},"B":{"0":2.5656459463,"1":1.3403088498,"2":-0.2261692849,"3":0.8138502857,"4":-0.8273169356},"A":{"0":-1.2064117817,"1":1.4312559863,"2":-1.1702987971,"3":0.4108345112,"4":0.1320031703}}'

以ISO日期格式写入,以微秒为单位

In [188]: json = dfd.to_json(date_format='iso', date_unit='us')

In [189]: json
Out[189]: '{"date":{"0":"2013-01-01T00:00:00.000000Z","1":"2013-01-01T00:00:00.000000Z","2":"2013-01-01T00:00:00.000000Z","3":"2013-01-01T00:00:00.000000Z","4":"2013-01-01T00:00:00.000000Z"},"B":{"0":2.5656459463,"1":1.3403088498,"2":-0.2261692849,"3":0.8138502857,"4":-0.8273169356},"A":{"0":-1.2064117817,"1":1.4312559863,"2":-1.1702987971,"3":0.4108345112,"4":0.1320031703}}'

Epoch时间戳,以秒为单位

In [190]: json = dfd.to_json(date_format='epoch', date_unit='s')

In [191]: json
Out[191]: '{"date":{"0":1356998400,"1":1356998400,"2":1356998400,"3":1356998400,"4":1356998400},"B":{"0":2.5656459463,"1":1.3403088498,"2":-0.2261692849,"3":0.8138502857,"4":-0.8273169356},"A":{"0":-1.2064117817,"1":1.4312559863,"2":-1.1702987971,"3":0.4108345112,"4":0.1320031703}}'

写入文件,包含日期索引和日期列

In [192]: dfj2 = dfj.copy()

In [193]: dfj2['date'] = pd.Timestamp('20130101')

In [194]: dfj2['ints'] = list(range(5))

In [195]: dfj2['bools'] = True

In [196]: dfj2.index = pd.date_range('20130101', periods=5)

In [197]: dfj2.to_json('test.json')

In [198]: open('test.json').read()
Out[198]: '{"A":{"1356998400000":-1.2945235903,"1357084800000":0.2766617129,"1357171200000":-0.0139597524,"1357257600000":-0.0061535699,"1357344000000":0.8957173022},"B":{"1356998400000":0.4137381054,"1357084800000":-0.472034511,"1357171200000":-0.3625429925,"1357257600000":-0.923060654,"1357344000000":0.8052440254},"date":{"1356998400000":1356998400000,"1357084800000":1356998400000,"1357171200000":1356998400000,"1357257600000":1356998400000,"1357344000000":1356998400000},"ints":{"1356998400000":0,"1357084800000":1,"1357171200000":2,"1357257600000":3,"1357344000000":4},"bools":{"1356998400000":true,"1357084800000":true,"1357171200000":true,"1357257600000":true,"1357344000000":true}}'

Fallback Behavior

如果JSON序列化器不能直接处理容器内容,它将以以下方式回退:

  • 如果dtype不被支持(例如np.complex),那么将为每个值调用default_handler(如果提供),否则会引发异常。
  • 如果对象不受支持,它将尝试以下操作:
    • 检查对象是否定义了toDict方法并调用它。toDict方法应返回一个dict,然后将JSON序列化。
    • 调用default_handler(如果提供)。
    • 通过遍历其内容将对象转换为dict但是,这通常会失败并显示OverflowError或给出意外的结果。

一般来说,不受支持的对象或类型的最佳方法是提供一个default_handler例如:

DataFrame([1.0, 2.0, complex(1.0, 2.0)]).to_json()  # raises

RuntimeError: Unhandled numpy dtype 15

可以通过指定一个简单的default_handler来处理:

In [199]: pd.DataFrame([1.0, 2.0, complex(1.0, 2.0)]).to_json(default_handler=str)
Out[199]: '{"0":{"0":"(1+0j)","1":"(2+0j)","2":"(1+2j)"}}'

Reading JSON

读取JSON字符串到pandas对象可以取多个参数。如果未提供typNone,解析器将尝试解析DataFrame要明确强制Series解析,请传递typ=series

如果JSON不可解析,解析器将产生ValueError/TypeError/AssertionError之一。

如果在编码为JSON时使用非默认orient,则必须在此处传递相同的选项,以便解码产生合理的结果,有关概述,请参见Orient选项

Data Conversion

默认为convert_axes=Truedtype=Trueconvert_dates=True会尝试解析轴,类型,包括日期。如果您需要覆盖特定的dtypes,请传递一个dict到dtype如果您需要在轴中保留字符串状数字(例如“1”,“2”),则只应将convert_axes设置为False

注意

如果convert_dates=True,且数据和/或列标签显示为“日期样”,则大整数值可以转换为日期。确切的阈值取决于指定的date_unit“日期样”表示列标签满足以下条件之一:

  • 它以'_at'结尾
  • 它以'_time'结尾
  • 它从'timestamp'开始
  • 它是'modified'
  • 它是'date'

警告

当读取JSON数据时,自动强制转换为dtypes有一些怪癖:

  • 可以按照与序列化不同的顺序重建索引,也就是说,返回的顺序不能保证与序列化之前相同
  • 如果可以安全地执行,则float数据的列将转换为integer。一列1.
  • bool列将在重建时转换为integer

因此,有时您可能需要通过dtype关键字参数指定特定的dtypes。

从JSON字符串读取:

In [200]: pd.read_json(json)
Out[200]: 
          A         B       date
0 -1.206412  2.565646 2013-01-01
1  1.431256  1.340309 2013-01-01
2 -1.170299 -0.226169 2013-01-01
3  0.410835  0.813850 2013-01-01
4  0.132003 -0.827317 2013-01-01

从文件读取:

In [201]: pd.read_json('test.json')
Out[201]: 
                   A         B bools       date  ints
2013-01-01 -1.294524  0.413738  True 2013-01-01     0
2013-01-02  0.276662 -0.472035  True 2013-01-01     1
2013-01-03 -0.013960 -0.362543  True 2013-01-01     2
2013-01-04 -0.006154 -0.923061  True 2013-01-01     3
2013-01-05  0.895717  0.805244  True 2013-01-01     4

不转换任何数据(但仍然转换轴和日期):

In [202]: pd.read_json('test.json', dtype=object).dtypes
Out[202]: 
A        object
B        object
bools    object
date     object
ints     object
dtype: object

指定转换的类型:

In [203]: pd.read_json('test.json', dtype={'A' : 'float32', 'bools' : 'int8'}).dtypes
Out[203]: 
A               float32
B               float64
bools              int8
date     datetime64[ns]
ints              int64
dtype: object

保留字符串索引:

In [204]: si = pd.DataFrame(np.zeros((4, 4)),
   .....:          columns=list(range(4)),
   .....:          index=[str(i) for i in range(4)])
   .....: 

In [205]: si
Out[205]: 
     0    1    2    3
0  0.0  0.0  0.0  0.0
1  0.0  0.0  0.0  0.0
2  0.0  0.0  0.0  0.0
3  0.0  0.0  0.0  0.0

In [206]: si.index
Out[206]: Index([u'0', u'1', u'2', u'3'], dtype='object')

In [207]: si.columns
Out[207]: Int64Index([0, 1, 2, 3], dtype='int64')

In [208]: json = si.to_json()

In [209]: sij = pd.read_json(json, convert_axes=False)

In [210]: sij
Out[210]: 
   0  1  2  3
0  0  0  0  0
1  0  0  0  0
2  0  0  0  0
3  0  0  0  0

In [211]: sij.index
Out[211]: Index([u'0', u'1', u'2', u'3'], dtype='object')

In [212]: sij.columns
Out[212]: Index([u'0', u'1', u'2', u'3'], dtype='object')

以纳秒为单位写入的日期需要以纳秒为单位进行读取:

In [213]: json = dfj2.to_json(date_unit='ns')

# Try to parse timestamps as millseconds -> Won't Work
In [214]: dfju = pd.read_json(json, date_unit='ms')

In [215]: dfju
Out[215]: 
                            A         B bools                 date  ints
1356998400000000000 -1.294524  0.413738  True  1356998400000000000     0
1357084800000000000  0.276662 -0.472035  True  1356998400000000000     1
1357171200000000000 -0.013960 -0.362543  True  1356998400000000000     2
1357257600000000000 -0.006154 -0.923061  True  1356998400000000000     3
1357344000000000000  0.895717  0.805244  True  1356998400000000000     4

# Let pandas detect the correct precision
In [216]: dfju = pd.read_json(json)

In [217]: dfju
Out[217]: 
                   A         B bools       date  ints
2013-01-01 -1.294524  0.413738  True 2013-01-01     0
2013-01-02  0.276662 -0.472035  True 2013-01-01     1
2013-01-03 -0.013960 -0.362543  True 2013-01-01     2
2013-01-04 -0.006154 -0.923061  True 2013-01-01     3
2013-01-05  0.895717  0.805244  True 2013-01-01     4

# Or specify that all timestamps are in nanoseconds
In [218]: dfju = pd.read_json(json, date_unit='ns')

In [219]: dfju
Out[219]: 
                   A         B bools       date  ints
2013-01-01 -1.294524  0.413738  True 2013-01-01     0
2013-01-02  0.276662 -0.472035  True 2013-01-01     1
2013-01-03 -0.013960 -0.362543  True 2013-01-01     2
2013-01-04 -0.006154 -0.923061  True 2013-01-01     3
2013-01-05  0.895717  0.805244  True 2013-01-01     4

The Numpy Parameter

注意

这仅支持数值数据。索引和列标签可以是非数字的,例如。字符串,日期等。

如果numpy=True被传递到read_json,将尝试在反序列化期间侦听适当的dtype,然后直接解码为numpy数组,绕过对中间Python对象。

如果你反序列化大量的数值数据,这可以提供加速:

In [220]: randfloats = np.random.uniform(-100, 1000, 10000)

In [221]: randfloats.shape = (1000, 10)

In [222]: dffloats = pd.DataFrame(randfloats, columns=list('ABCDEFGHIJ'))

In [223]: jsonfloats = dffloats.to_json()
In [224]: timeit pd.read_json(jsonfloats)
100 loops, best of 3: 12.2 ms per loop
In [225]: timeit pd.read_json(jsonfloats, numpy=True)
100 loops, best of 3: 7.35 ms per loop

对于较小的数据集,加速不太明显:

In [226]: jsonfloats = dffloats.head(100).to_json()
In [227]: timeit pd.read_json(jsonfloats)
100 loops, best of 3: 5.72 ms per loop
In [228]: timeit pd.read_json(jsonfloats, numpy=True)
100 loops, best of 3: 4.94 ms per loop

警告

直接numpy解码进行了许多假设,如果不满足这些假设,可能会失败或产生意外的输出:

  • 数据是数字。
  • 数据是均匀的。dtype从解码的第一个值被嗅探。可能会出现ValueError,如果不满足此条件,可能会产生不正确的输出。
  • 标签是有序的。仅从第一个容器中读取标签,假定每个后续行/列都按相同的顺序进行编码。如果数据使用to_json编码,则应满足此要求,但如果JSON来自其他来源,则可能不是这样。

Normalization

版本0.13.0中的新功能。

pandas提供了一个实用函数来接受一个dict或list的列表,并将这个半结构化数据正规化到一个平面表中。

In [229]: from pandas.io.json import json_normalize

In [230]: data = [{'state': 'Florida',
   .....:           'shortname': 'FL',
   .....:           'info': {
   .....:                'governor': 'Rick Scott'
   .....:           },
   .....:           'counties': [{'name': 'Dade', 'population': 12345},
   .....:                       {'name': 'Broward', 'population': 40000},
   .....:                       {'name': 'Palm Beach', 'population': 60000}]},
   .....:          {'state': 'Ohio',
   .....:           'shortname': 'OH',
   .....:           'info': {
   .....:                'governor': 'John Kasich'
   .....:           },
   .....:           'counties': [{'name': 'Summit', 'population': 1234},
   .....:                        {'name': 'Cuyahoga', 'population': 1337}]}]
   .....: 

In [231]: json_normalize(data, 'counties', ['state', 'shortname', ['info', 'governor']])
Out[231]: 
         name  population info.governor    state shortname
0        Dade       12345    Rick Scott  Florida        FL
1     Broward       40000    Rick Scott  Florida        FL
2  Palm Beach       60000    Rick Scott  Florida        FL
3      Summit        1234   John Kasich     Ohio        OH
4    Cuyahoga        1337   John Kasich     Ohio        OH

Line delimited json

版本0.19.0中的新功能。

pandas能够读取和写入使用Hadoop或Spark在数据处理管道中常见的行分隔的json文件。

In [232]: jsonl = '''
   .....:     {"a":1,"b":2}
   .....:     {"a":3,"b":4}
   .....: '''
   .....: 

In [233]: df = pd.read_json(jsonl, lines=True)

In [234]: df
Out[234]: 
   a  b
0  1  2
1  3  4

In [235]: df.to_json(orient='records', lines=True)
Out[235]: u'{"a":1,"b":2}\n{"a":3,"b":4}'

HTML

Reading HTML Content

警告

我们高度鼓励您阅读关于BeautifulSoup4 / html5lib / lxml解析器相关问题的HTML parsing gotchas

版本0.12.0中的新功能。

顶层read_html()函数可以接受HTML字符串/文件/ URL,并将HTML表解析为pandas DataFrames列表。让我们来看几个例子。

注意

read_html返回DataFrame对象的list,即使HTML内容中只包含一个表

读取没有选项的网址

In [236]: url = 'http://www.fdic.gov/bank/individual/failed/banklist.html'

In [237]: dfs = pd.read_html(url)

In [238]: dfs
Out[238]: 
[                             Bank Name             City  ST   CERT  \
 0                          Allied Bank         Mulberry  AR     91   
 1         The Woodbury Banking Company         Woodbury  GA  11297   
 2               First CornerStone Bank  King of Prussia  PA  35312   
 3                   Trust Company Bank          Memphis  TN   9956   
 4           North Milwaukee State Bank        Milwaukee  WI  20364   
 5               Hometown National Bank         Longview  WA  35156   
 6                  The Bank of Georgia   Peachtree City  GA  35259   
 ..                                 ...              ...  ..    ...   
 540      Hamilton Bank, NA  En Espanol            Miami  FL  24382   
 541             Sinclair National Bank         Gravette  AR  34248   
 542                 Superior Bank, FSB         Hinsdale  IL  32646   
 543                Malta National Bank            Malta  OH   6629   
 544    First Alliance Bank & Trust Co.       Manchester  NH  34264   
 545  National State Bank of Metropolis       Metropolis  IL   3815   
 546                   Bank of Honolulu         Honolulu  HI  21029   
 
                    Acquiring Institution        Closing Date  \
 0                           Today's Bank  September 23, 2016   
 1                            United Bank     August 19, 2016   
 2    First-Citizens Bank & Trust Company         May 6, 2016   
 3             The Bank of Fayette County      April 29, 2016   
 4    First-Citizens Bank & Trust Company      March 11, 2016   
 5                         Twin City Bank     October 2, 2015   
 6                          Fidelity Bank     October 2, 2015   
 ..                                   ...                 ...   
 540     Israel Discount Bank of New York    January 11, 2002   
 541                   Delta Trust & Bank   September 7, 2001   
 542                Superior Federal, FSB       July 27, 2001   
 543                    North Valley Bank         May 3, 2001   
 544  Southern New Hampshire Bank & Trust    February 2, 2001   
 545              Banterra Bank of Marion   December 14, 2000   
 546                   Bank of the Orient    October 13, 2000   
 
            Updated Date  
 0     November 17, 2016  
 1     November 17, 2016  
 2     September 6, 2016  
 3     September 6, 2016  
 4         June 16, 2016  
 5        April 13, 2016  
 6      October 24, 2016  
 ..                  ...  
 540  September 21, 2015  
 541   February 10, 2004  
 542     August 19, 2014  
 543   November 18, 2002  
 544   February 18, 2003  
 545      March 17, 2005  
 546      March 17, 2005  
 
 [547 rows x 7 columns]]

注意

来自上述URL的数据每个星期一都会更改,因此上面生成的数据和下面的数据可能会略有不同。

从上述网址读取文件的内容,并将其作为字符串传递给read_html

In [239]: with open(file_path, 'r') as f:
   .....:     dfs = pd.read_html(f.read())
   .....: 

In [240]: dfs
Out[240]: 
[                                    Bank Name          City  ST   CERT  \
 0    Banks of Wisconsin d/b/a Bank of Kenosha       Kenosha  WI  35386   
 1                        Central Arizona Bank    Scottsdale  AZ  34527   
 2                                Sunrise Bank      Valdosta  GA  58185   
 3                       Pisgah Community Bank     Asheville  NC  58701   
 4                         Douglas County Bank  Douglasville  GA  21649   
 5                                Parkway Bank        Lenoir  NC  57158   
 6                      Chipola Community Bank      Marianna  FL  58034   
 ..                                        ...           ...  ..    ...   
 499               Hamilton Bank, NAEn Espanol         Miami  FL  24382   
 500                    Sinclair National Bank      Gravette  AR  34248   
 501                        Superior Bank, FSB      Hinsdale  IL  32646   
 502                       Malta National Bank         Malta  OH   6629   
 503           First Alliance Bank & Trust Co.    Manchester  NH  34264   
 504         National State Bank of Metropolis    Metropolis  IL   3815   
 505                          Bank of Honolulu      Honolulu  HI  21029   
 
                    Acquiring Institution       Closing Date       Updated Date  
 0                  North Shore Bank, FSB       May 31, 2013       May 31, 2013  
 1                     Western State Bank       May 14, 2013       May 20, 2013  
 2                           Synovus Bank       May 10, 2013       May 21, 2013  
 3                     Capital Bank, N.A.       May 10, 2013       May 14, 2013  
 4                    Hamilton State Bank     April 26, 2013       May 16, 2013  
 5       CertusBank, National Association     April 26, 2013       May 17, 2013  
 6          First Federal Bank of Florida     April 19, 2013       May 16, 2013  
 ..                                   ...                ...                ...  
 499     Israel Discount Bank of New York   January 11, 2002       June 5, 2012  
 500                   Delta Trust & Bank  September 7, 2001  February 10, 2004  
 501                Superior Federal, FSB      July 27, 2001       June 5, 2012  
 502                    North Valley Bank        May 3, 2001  November 18, 2002  
 503  Southern New Hampshire Bank & Trust   February 2, 2001  February 18, 2003  
 504              Banterra Bank of Marion  December 14, 2000     March 17, 2005  
 505                   Bank of the Orient   October 13, 2000     March 17, 2005  
 
 [506 rows x 7 columns]]

如果你愿意,你甚至可以传递StringIO的实例

In [241]: with open(file_path, 'r') as f:
   .....:     sio = StringIO(f.read())
   .....: 

In [242]: dfs = pd.read_html(sio)

In [243]: dfs
Out[243]: 
[                                    Bank Name          City  ST   CERT  \
 0    Banks of Wisconsin d/b/a Bank of Kenosha       Kenosha  WI  35386   
 1                        Central Arizona Bank    Scottsdale  AZ  34527   
 2                                Sunrise Bank      Valdosta  GA  58185   
 3                       Pisgah Community Bank     Asheville  NC  58701   
 4                         Douglas County Bank  Douglasville  GA  21649   
 5                                Parkway Bank        Lenoir  NC  57158   
 6                      Chipola Community Bank      Marianna  FL  58034   
 ..                                        ...           ...  ..    ...   
 499               Hamilton Bank, NAEn Espanol         Miami  FL  24382   
 500                    Sinclair National Bank      Gravette  AR  34248   
 501                        Superior Bank, FSB      Hinsdale  IL  32646   
 502                       Malta National Bank         Malta  OH   6629   
 503           First Alliance Bank & Trust Co.    Manchester  NH  34264   
 504         National State Bank of Metropolis    Metropolis  IL   3815   
 505                          Bank of Honolulu      Honolulu  HI  21029   
 
                    Acquiring Institution       Closing Date       Updated Date  
 0                  North Shore Bank, FSB       May 31, 2013       May 31, 2013  
 1                     Western State Bank       May 14, 2013       May 20, 2013  
 2                           Synovus Bank       May 10, 2013       May 21, 2013  
 3                     Capital Bank, N.A.       May 10, 2013       May 14, 2013  
 4                    Hamilton State Bank     April 26, 2013       May 16, 2013  
 5       CertusBank, National Association     April 26, 2013       May 17, 2013  
 6          First Federal Bank of Florida     April 19, 2013       May 16, 2013  
 ..                                   ...                ...                ...  
 499     Israel Discount Bank of New York   January 11, 2002       June 5, 2012  
 500                   Delta Trust & Bank  September 7, 2001  February 10, 2004  
 501                Superior Federal, FSB      July 27, 2001       June 5, 2012  
 502                    North Valley Bank        May 3, 2001  November 18, 2002  
 503  Southern New Hampshire Bank & Trust   February 2, 2001  February 18, 2003  
 504              Banterra Bank of Marion  December 14, 2000     March 17, 2005  
 505                   Bank of the Orient   October 13, 2000     March 17, 2005  
 
 [506 rows x 7 columns]]

注意

以下示例不是由IPython评估程序运行的,因为有这么多网络访问功能会减慢文档构建。如果您发现错误或无法运行的示例,请随时在pandas GitHub问题页面上报告错误。

读取网址并匹配包含特定文本的表

match = 'Metcalf Bank'
df_list = pd.read_html(url, match=match)

指定标题行(默认情况下,<th>元素用于形成列索引);如果指定,则从数据减去经解析的报头元素(<th>

dfs = pd.read_html(url, header=0)

指定索引列

dfs = pd.read_html(url, index_col=0)

指定要跳过的行数

dfs = pd.read_html(url, skiprows=0)

使用列表指定要跳过的行数(xrange(仅限Python 2))

dfs = pd.read_html(url, skiprows=range(2))

指定HTML属性

dfs1 = pd.read_html(url, attrs={'id': 'table'})
dfs2 = pd.read_html(url, attrs={'class': 'sortable'})
print(np.array_equal(dfs1[0], dfs2[0]))  # Should be True

指定应转换为NaN的值

dfs = pd.read_html(url, na_values=['No Acquirer'])

版本0.19中的新功能。

指定是否保留默认的NaN值集

dfs = pd.read_html(url, keep_default_na=False)

版本0.19中的新功能。

指定列的转换器。这对于具有前导零的数字文本数据很有用。默认情况下,数值型的列转换为数字类型,前导零将丢失。为了避免这种情况,我们可以将这些列转换为字符串。

url_mcc = 'https://en.wikipedia.org/wiki/Mobile_country_code'
dfs = pd.read_html(url_mcc, match='Telekom Albania', header=0, converters={'MNC':
str})

版本0.19中的新功能。

使用上述的一些组合

dfs = pd.read_html(url, match='Metcalf Bank', index_col=0)

读入pandas to_html输出(浮点精度有些损失)

df = pd.DataFrame(randn(2, 2))
s = df.to_html(float_format='{0:.40g}'.format)
dfin = pd.read_html(s, index_col=0)

The lxml backend will raise an error on a failed parse if that is the only parser you provide (if you only have a single parser you can provide just a string, but it is considered good practice to pass a list with one string if, for example, the function expects a sequence of strings)

dfs = pd.read_html(url, 'Metcalf Bank', index_col=0, flavor=['lxml'])

要么

dfs = pd.read_html(url, 'Metcalf Bank', index_col=0, flavor='lxml')

但是,如果您安装了bs4和html5lib,并通过None['lxml', 'bs4'] 那么解析将很可能成功。请注意,一旦解析成功,函数将返回

dfs = pd.read_html(url, 'Metcalf Bank', index_col=0, flavor=['lxml', 'bs4'])

Writing to HTML files

DataFrame对象具有实例方法to_html,它将DataFrame的内容呈现为HTML表。函数参数与上述方法to_string中的相同。

注意

为了简洁起见,此处并未显示DataFrame.to_html的所有可能选项。有关完整的选项集,请参见to_html()

In [244]: df = pd.DataFrame(randn(2, 2))

In [245]: df
Out[245]: 
          0         1
0 -0.184744  0.496971
1 -0.856240  1.857977

In [246]: print(df.to_html())  # raw html
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>0</th>
      <th>1</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>-0.184744</td>
      <td>0.496971</td>
    </tr>
    <tr>
      <th>1</th>
      <td>-0.856240</td>
      <td>1.857977</td>
    </tr>
  </tbody>
</table>

HTML:

0 1
0 -0.184744 0.496971
1 -0.856240 1.857977

columns参数将限制显示的列

In [247]: print(df.to_html(columns=[0]))
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>0</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>-0.184744</td>
    </tr>
    <tr>
      <th>1</th>
      <td>-0.856240</td>
    </tr>
  </tbody>
</table>

HTML:

0
0 -0.184744
1 -0.856240

float_format使用Python可调用方法来控制浮点值的精度

In [248]: print(df.to_html(float_format='{0:.10f}'.format))
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>0</th>
      <th>1</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>-0.1847438576</td>
      <td>0.4969711327</td>
    </tr>
    <tr>
      <th>1</th>
      <td>-0.8562396763</td>
      <td>1.8579766508</td>
    </tr>
  </tbody>
</table>

HTML:

0 1
0 -0.1847438576 0.4969711327
1 -0.8562396763 1.8579766508

bold_rows会使行标签默认为粗体,但您可以关闭它

In [249]: print(df.to_html(bold_rows=False))
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>0</th>
      <th>1</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>0</td>
      <td>-0.184744</td>
      <td>0.496971</td>
    </tr>
    <tr>
      <td>1</td>
      <td>-0.856240</td>
      <td>1.857977</td>
    </tr>
  </tbody>
</table>
0 1
0 -0.184744 0.496971
1 -0.856240 1.857977

classes参数提供了给出生成的HTML表CSS类的能力。请注意,这些类是附加到现有的'dataframe'类。

In [250]: print(df.to_html(classes=['awesome_table_class', 'even_more_awesome_class']))
<table border="1" class="dataframe awesome_table_class even_more_awesome_class">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>0</th>
      <th>1</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>-0.184744</td>
      <td>0.496971</td>
    </tr>
    <tr>
      <th>1</th>
      <td>-0.856240</td>
      <td>1.857977</td>
    </tr>
  </tbody>
</table>

最后,escape参数允许您控制在生成的HTML中转义的“”和“&”字符(默认为True)。因此,要获取没有转义字符的HTML,请传递escape=False

In [251]: df = pd.DataFrame({'a': list('&<>'), 'b': randn(3)})

转义:

In [252]: print(df.to_html())
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>a</th>
      <th>b</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>&amp;</td>
      <td>-0.474063</td>
    </tr>
    <tr>
      <th>1</th>
      <td>&lt;</td>
      <td>-0.230305</td>
    </tr>
    <tr>
      <th>2</th>
      <td>&gt;</td>
      <td>-0.400654</td>
    </tr>
  </tbody>
</table>
一个 b
0 &lt; -0.474063
1 -0.230305
2 > -0.400654

未逸出:

In [253]: print(df.to_html(escape=False))
<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>a</th>
      <th>b</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>&</td>
      <td>-0.474063</td>
    </tr>
    <tr>
      <th>1</th>
      <td><</td>
      <td>-0.230305</td>
    </tr>
    <tr>
      <th>2</th>
      <td>></td>
      <td>-0.400654</td>
    </tr>
  </tbody>
</table>
一个 b
0 &lt; -0.474063
1 -0.230305
2 > -0.400654

注意

某些浏览器可能不会在前两个HTML表格的呈现方面显示不同。

Excel files

The read_excel() method can read Excel 2003 (.xls) and Excel 2007+ (.xlsx) files using the xlrd Python module. to_excel()实例方法用于将DataFrame保存到Excel。通常,语义与使用csv数据类似。有关某些高级策略,请参阅cookbook

Reading Excel Files

在最基本的用例中,read_excel获取Excel文件的路径,sheetname指示要解析的工作表。

# Returns a DataFrame
read_excel('path_to_file.xls', sheetname='Sheet1')

ExcelFile class

为了方便使用同一文件中的多个工作表,可以使用ExcelFile类包装文件,并将其传递到read_excel多张纸作为文件只读入内存一次。

xlsx = pd.ExcelFile('path_to_file.xls)
df = pd.read_excel(xlsx, 'Sheet1')

ExcelFile类也可以用作上下文管理器。

with pd.ExcelFile('path_to_file.xls') as xls:
    df1 = pd.read_excel(xls, 'Sheet1')
    df2 = pd.read_excel(xls, 'Sheet2')

sheet_names属性将生成文件中的工作表名称列表。

ExcelFile的主要用例是解析具有不同参数的多个工作表

data = {}
# For when Sheet1's format differs from Sheet2
with pd.ExcelFile('path_to_file.xls') as xls:
    data['Sheet1'] = pd.read_excel(xls, 'Sheet1', index_col=None, na_values=['NA'])
    data['Sheet2'] = pd.read_excel(xls, 'Sheet2', index_col=1)

请注意,如果对所有工作表使用相同的解析参数,则可以将工作表名称列表传递到read_excel,而不会降低性能。

# using the ExcelFile class
data = {}
with pd.ExcelFile('path_to_file.xls') as xls:
    data['Sheet1'] = read_excel(xls, 'Sheet1', index_col=None, na_values=['NA'])
    data['Sheet2'] = read_excel(xls, 'Sheet2', index_col=None, na_values=['NA'])

# equivalent using the read_excel function
data = read_excel('path_to_file.xls', ['Sheet1', 'Sheet2'], index_col=None, na_values=['NA'])

版本0.12中的新功能。

ExcelFile已移至顶层命名空间。

版本0.17中的新功能。

read_excel可以使用ExcelFile对象作为输入

Specifying Sheets

注意

第二个参数是sheetname,不要与ExcelFile.sheet_names混淆

注意

ExcelFile的属性sheet_names提供对工作表列表的访问。

  • 参数sheetname允许指定要读取的工作表。
  • sheetname的默认值为0,表示要读取第一张工作表
  • 传递字符串以引用工作簿中特定工作表的名称。
  • 传递整数以引用表单的索引。索引遵循Python约定,从0开始。
  • 传递字符串或整数的列表,返回指定工作表的字典。
  • 传递None可返回所有可用工作表的字典。
# Returns a DataFrame
read_excel('path_to_file.xls', 'Sheet1', index_col=None, na_values=['NA'])

使用表索引:

# Returns a DataFrame
read_excel('path_to_file.xls', 0, index_col=None, na_values=['NA'])

使用所有默认值:

# Returns a DataFrame
read_excel('path_to_file.xls')

使用无获取所有工作表:

# Returns a dictionary of DataFrames
read_excel('path_to_file.xls',sheetname=None)

使用列表获取多个工作表:

# Returns the 1st and 4th sheet, as a dictionary of DataFrames.
read_excel('path_to_file.xls',sheetname=['Sheet1',3])

版本0.16中的新功能。

read_excel可以读取多个工作表,方法是将sheetname设置为工作表名称列表,工作表位置列表或None表示读取所有的表格。

版本0.13中的新功能。

可以通过工作表索引或工作表名称分别使用整数或字符串指定工作表。

Reading a MultiIndex

版本0.17中的新功能。

read_excel can read a MultiIndex index, by passing a list of columns to index_col and a MultiIndex column by passing a list of rows to header. 如果indexcolumns具有序列化的级别名称,那么通过指定组成级别的行/列,也将读入。

例如,要读取不带名称的MultiIndex索引:

In [254]: df = pd.DataFrame({'a':[1,2,3,4], 'b':[5,6,7,8]},
   .....:                   index=pd.MultiIndex.from_product([['a','b'],['c','d']]))
   .....: 

In [255]: df.to_excel('path_to_file.xlsx')

In [256]: df = pd.read_excel('path_to_file.xlsx', index_col=[0,1])

In [257]: df
Out[257]: 
     a  b
a c  1  5
  d  2  6
b c  3  7
  d  4  8

如果索引具有级别名称,则它们将使用相同的参数进行解析。

In [258]: df.index = df.index.set_names(['lvl1', 'lvl2'])

In [259]: df.to_excel('path_to_file.xlsx')

In [260]: df = pd.read_excel('path_to_file.xlsx', index_col=[0,1])

In [261]: df
Out[261]: 
           a  b
lvl1 lvl2      
a    c     1  5
     d     2  6
b    c     3  7
     d     4  8

如果源文件同时具有MultiIndex索引和列,则指定每个列的列表应传递到index_colheader

In [262]: df.columns = pd.MultiIndex.from_product([['a'],['b', 'd']], names=['c1', 'c2'])

In [263]: df.to_excel('path_to_file.xlsx')

In [264]: df = pd.read_excel('path_to_file.xlsx',
   .....:                     index_col=[0,1], header=[0,1])
   .....: 

In [265]: df
Out[265]: 
c1         a   
c2         b  d
lvl1 lvl2      
a    c     1  5
     d     2  6
b    c     3  7
     d     4  8

警告

保存在版本0.16.2或之前的具有索引名称的Excel文件仍然可以读入,但has_index_names参数必须指定为True

Parsing Specific Columns

通常情况下,用户将插入列以在Excel中进行临时计算,并且您可能不想读取这些列。read_excel使用parse_cols关键字,以允许您指定要解析的列子集。

如果parse_cols是整数,则假定指示要解析的最后一列。

read_excel('path_to_file.xls', 'Sheet1', parse_cols=2)

如果parse_cols是整数列表,则假定它是要解析的文件列索引。

read_excel('path_to_file.xls', 'Sheet1', parse_cols=[0, 2, 3])

Cell Converters

可以通过转换器选项转换Excel单元格的内容。例如,要将列转换为布尔值:

read_excel('path_to_file.xls', 'Sheet1', converters={'MyBools': bool})

此选项处理缺少的值,并将转换器中的异常视为缺失数据。转换是逐个单元格应用的,而不是作为一个整体应用到列,因此不能保证数组dtype。例如,具有缺失值的整数列不能转换为具有整数dtype的数组,因为NaN严格来说是一个浮点数。您可以手动掩蔽缺少的数据以恢复整数dtype:

cfun = lambda x: int(x) if x else -1
read_excel('path_to_file.xls', 'Sheet1', converters={'MyInts': cfun})

Writing Excel Files

Writing Excel Files to Disk

要将DataFrame对象写入Excel文件的工作表,可以使用to_excel实例方法。参数与上述的to_csv基本相同,第一个参数是excel文件的名称,第二个参数是可选的第二个参数应该写入DataFrame的工作表的名称。例如:

df.to_excel('path_to_file.xlsx', sheet_name='Sheet1')

Files with a .xls extension will be written using xlwt and those with a .xlsx extension will be written using xlsxwriter (if available) or openpyxl.

DataFrame将以尝试模仿REPL输出的方式写入。与0.12.0的一个区别是,index_label将放置在第二行,而不是第一行。您可以通过将to_excel()中的merge_cells选项设置为False来获取先前的行为:

df.to_excel('path_to_file.xlsx', index_label='label', merge_cells=False)

Panel类还有一个to_excel实例方法,它将Panel中的每个DataFrame写入单独的工作表。

为了在单个Excel文件中将单独的DataFrames写入单独的工作表,可以传递ExcelWriter

with ExcelWriter('path_to_file.xlsx') as writer:
    df1.to_excel(writer, sheet_name='Sheet1')
    df2.to_excel(writer, sheet_name='Sheet2')

注意

read_excel在内部,Excel将所有数字数据存储为浮点数。因为这可能在读取数据时产生意想不到的行为,如果pandas不丢失信息,则默认为试图将整数转换为浮点数(1.0 - > 1)。您可以传递convert_float=False以禁用此行为,这可能会略微提高性能。

Writing Excel Files to Memory

版本0.17中的新功能。

Pandas支持使用ExcelWriter将Excel文件写入缓冲区对象,例如StringIOBytesIO

版本0.17中的新功能。

添加了对Openpyxl> = 2.2的支持

# Safe import for either Python 2.x or 3.x
try:
    from io import BytesIO
except ImportError:
    from cStringIO import StringIO as BytesIO

bio = BytesIO()

# By setting the 'engine' in the ExcelWriter constructor.
writer = ExcelWriter(bio, engine='xlsxwriter')
df.to_excel(writer, sheet_name='Sheet1')

# Save the workbook
writer.save()

# Seek to the beginning and read to copy the workbook to a variable in memory
bio.seek(0)
workbook = bio.read()

注意

engine是可选的,但建议使用。设置引擎将确定生成的工作簿的版本。设置engine='xlrd'将生成Excel 2003格式的工作簿(xls)。使用'openpyxl''xlsxwriter'将生成Excel 2007格式的工作簿(xlsx)。如果省略,则会生成Excel 2007格式的工作簿。

Excel writer engines

版本0.13中的新功能。

pandas通过两种方法选择Excel写程序:

  1. engine关键字参数
  2. 文件扩展名(通过config选项中指定的默认值)

默认情况下,pandas使用XlsxWriter表示.xlsxopenpyxl表示.xlsm文件和xlwt用于.xls文件。如果您安装了多个引擎,可以通过setting the config options io.excel.xlsx.writerio.excel.xls.writer对于.xlsx文件,如果Xlsxwriter不可用,pandas将回退到openpyxl

要指定要使用的写入程序,可以将引擎关键字参数传递到to_excelExcelWriter内置引擎是:

# By setting the 'engine' in the DataFrame and Panel 'to_excel()' methods.
df.to_excel('path_to_file.xlsx', sheet_name='Sheet1', engine='xlsxwriter')

# By setting the 'engine' in the ExcelWriter constructor.
writer = ExcelWriter('path_to_file.xlsx', engine='xlsxwriter')

# Or via pandas configuration.
from pandas import options
options.io.excel.xlsx.writer = 'xlsxwriter'

df.to_excel('path_to_file.xlsx', sheet_name='Sheet1')

Clipboard

抓取数据的一种方法是使用read_clipboard方法,它将剪贴板缓冲区的内容传递给read_table方法。例如,您可以将以下文本复制到剪贴板(在许多操作系统上为CTRL-C):

  A B C
x 1 4 p
y 2 5 q
z 3 6 r

然后通过调用将数据直接导入DataFrame:

clipdf = pd.read_clipboard()
In [266]: clipdf
Out[266]: 
   A  B  C
x  1  4  p
y  2  5  q
z  3  6  r

to_clipboard方法可用于将DataFrame的内容写入剪贴板。然后,您可以将剪贴板内容粘贴到其他应用程序(在许多操作系统上的CTRL-V)。这里我们说明将DataFrame写入剪贴板并读回。

In [267]: df = pd.DataFrame(randn(5,3))

In [268]: df
Out[268]: 
          0         1         2
0 -0.288267 -0.084905  0.004772
1  1.382989  0.343635 -1.253994
2 -0.124925  0.212244  0.496654
3  0.525417  1.238640 -1.210543
4 -1.175743 -0.172372 -0.734129

In [269]: df.to_clipboard()

In [270]: pd.read_clipboard()
Out[270]: 
          0         1         2
0 -0.288267 -0.084905  0.004772
1  1.382989  0.343635 -1.253994
2 -0.124925  0.212244  0.496654
3  0.525417  1.238640 -1.210543
4 -1.175743 -0.172372 -0.734129

我们可以看到,我们得到了相同的内容,我们以前写到剪贴板。

注意

您可能需要在Linux上安装xclip或xsel(使用gtk或PyQt4模块)来使用这些方法。

Pickling

所有的pandas对象都配备了使用Python的cPickle模块使用pickle格式将数据结构保存到磁盘的to_pickle方法。

In [271]: df
Out[271]: 
          0         1         2
0 -0.288267 -0.084905  0.004772
1  1.382989  0.343635 -1.253994
2 -0.124925  0.212244  0.496654
3  0.525417  1.238640 -1.210543
4 -1.175743 -0.172372 -0.734129

In [272]: df.to_pickle('foo.pkl')

pandas命名空间中的read_pickle函数可用于从文件加载任何腌制的pandas对象(或任何其他腌制对象)

In [273]: pd.read_pickle('foo.pkl')
Out[273]: 
          0         1         2
0 -0.288267 -0.084905  0.004772
1  1.382989  0.343635 -1.253994
2 -0.124925  0.212244  0.496654
3  0.525417  1.238640 -1.210543
4 -1.175743 -0.172372 -0.734129

警告

加载从不受信任的来源接收的pickled数据可能是不安全的。

请参阅:http://docs.python.org/2.7/library/pickle.html

警告

几个内部重构,0.13(Series Refactoring)和0.15(Index Refactoring)保留了与这些版本之前创建的pickles的兼容性。但是,这些必须用pd.read_pickle读取,而不是默认的python pickle.load有关详细说明,请参阅此问题

注意

这些方法以前是pd.savepd.load,在0.12.0之前,现在已被弃用。

msgpack (experimental)

版本0.13.0中的新功能。

从0.13.0开始,pandas支持对象序列化的msgpack格式。这是一种轻量级的便携式二进制格式,类似于二进制JSON,高度节省空间,并且在写入(串行化)和读取(反序列化)时提供良好的性能。

警告

这是熊猫的一个非常新的特点。我们打算在msgpack数据的io中提供某些优化。由于这被标记为实验库,所以存储格式在未来版本之前可能不稳定。

由于写入格式更改和其他问题:

包装 可以解压缩
pre-0.17 / Python 2 任何
pre-0.17 / Python 3 任何
0.17 / Python 2
  • 0.17 / Python 2
  • > = 0.18 /任何Python
0.17 / Python 3 > = 0.18 /任何Python
0.18 > = 0.18

阅读(旧版本打包的文件)是向后兼容的,除了在Python 2中用0.17打包的文件,在这种情况下只能在Python 2中解压缩。

In [274]: df = pd.DataFrame(np.random.rand(5,2),columns=list('AB'))

In [275]: df.to_msgpack('foo.msg')

In [276]: pd.read_msgpack('foo.msg')
Out[276]: 
          A         B
0  0.154336  0.710999
1  0.398096  0.765220
2  0.586749  0.293052
3  0.290293  0.710783
4  0.988593  0.062106

In [277]: s = pd.Series(np.random.rand(5),index=pd.date_range('20130101',periods=5))

你可以传递一个对象的列表,你会收到他们反序列化。

In [278]: pd.to_msgpack('foo.msg', df, 'foo', np.array([1,2,3]), s)

In [279]: pd.read_msgpack('foo.msg')
Out[279]: 
[          A         B
 0  0.154336  0.710999
 1  0.398096  0.765220
 2  0.586749  0.293052
 3  0.290293  0.710783
 4  0.988593  0.062106, 'foo', array([1, 2, 3]), 2013-01-01    0.690810
 2013-01-02    0.235907
 2013-01-03    0.712756
 2013-01-04    0.119599
 2013-01-05    0.023493
 Freq: D, dtype: float64]

您可以传递iterator=True来迭代解压缩的结果

In [280]: for o in pd.read_msgpack('foo.msg',iterator=True):
   .....:     print o
   .....: 
          A         B
0  0.154336  0.710999
1  0.398096  0.765220
2  0.586749  0.293052
3  0.290293  0.710783
4  0.988593  0.062106
foo
[1 2 3]
2013-01-01    0.690810
2013-01-02    0.235907
2013-01-03    0.712756
2013-01-04    0.119599
2013-01-05    0.023493
Freq: D, dtype: float64

您可以将append=True传递给编写器,以附加到现有包

In [281]: df.to_msgpack('foo.msg',append=True)

In [282]: pd.read_msgpack('foo.msg')
Out[282]: 
[          A         B
 0  0.154336  0.710999
 1  0.398096  0.765220
 2  0.586749  0.293052
 3  0.290293  0.710783
 4  0.988593  0.062106, 'foo', array([1, 2, 3]), 2013-01-01    0.690810
 2013-01-02    0.235907
 2013-01-03    0.712756
 2013-01-04    0.119599
 2013-01-05    0.023493
 Freq: D, dtype: float64,           A         B
 0  0.154336  0.710999
 1  0.398096  0.765220
 2  0.586749  0.293052
 3  0.290293  0.710783
 4  0.988593  0.062106]

与其他io方法不同,to_msgpack可用于每个对象基础上,df.to_msgpack()和使用顶层pd.to_msgpack(...)其中,您可以打包任意集合的python列表,dicts,标量,同时混合熊猫对象。

In [283]: pd.to_msgpack('foo2.msg', { 'dict' : [ { 'df' : df }, { 'string' : 'foo' }, { 'scalar' : 1. }, { 's' : s } ] })

In [284]: pd.read_msgpack('foo2.msg')
Out[284]: 
{'dict': ({'df':           A         B
   0  0.154336  0.710999
   1  0.398096  0.765220
   2  0.586749  0.293052
   3  0.290293  0.710783
   4  0.988593  0.062106},
  {'string': 'foo'},
  {'scalar': 1.0},
  {'s': 2013-01-01    0.690810
   2013-01-02    0.235907
   2013-01-03    0.712756
   2013-01-04    0.119599
   2013-01-05    0.023493
   Freq: D, dtype: float64})}

Read/Write API

Msgpacks也可以从字符串读取和写入字符串。

In [285]: df.to_msgpack()
Out[285]: '\x84\xa6blocks\x91\x86\xa5dtype\xa7float64\xa8compress\xc0\xa4locs\x86\xa4ndim\x01\xa5dtype\xa5int64\xa8compress\xc0\xa4data\xd8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\xa5shape\x91\x02\xa3typ\xa7ndarray\xa5shape\x92\x02\x05\xa6values\xc7P\x00\xa0\xab\xfb6H\xc1\xc3?\x98(oMgz\xd9?\x17\xaed\\\xa5\xc6\xe2?\xdc\xd0\x1bd(\x94\xd2?\xb5\xe8\xf5\x0e\x8d\xa2\xef?\x02D\xebO\x80\xc0\xe6?\x16\xbddQ\xae|\xe8?\x10?Ya[\xc1\xd2?\xa8\xfd\xcf\xa0\xbc\xbe\xe6? Z\xe1\ti\xcc\xaf?\xa5klass\xaaFloatBlock\xa4axes\x92\x86\xa4name\xc0\xa5dtype\xa6object\xa8compress\xc0\xa4data\x92\xc4\x01A\xc4\x01B\xa5klass\xa5Index\xa3typ\xa5index\x86\xa4name\xc0\xa4stop\x05\xa5start\x00\xa4step\x01\xa5klass\xaaRangeIndex\xa3typ\xabrange_index\xa3typ\xadblock_manager\xa5klass\xa9DataFrame'

此外,您可以连接字符串以生成原始对象的列表。

In [286]: pd.read_msgpack(df.to_msgpack() + s.to_msgpack())
Out[286]: 
[          A         B
 0  0.154336  0.710999
 1  0.398096  0.765220
 2  0.586749  0.293052
 3  0.290293  0.710783
 4  0.988593  0.062106, 2013-01-01    0.690810
 2013-01-02    0.235907
 2013-01-03    0.712756
 2013-01-04    0.119599
 2013-01-05    0.023493
 Freq: D, dtype: float64]

HDF5 (PyTables)

HDFStore是一个类似dict的对象,使用优秀的PyTables库,使用HDF5格式能快速读取和写入pandas。有关某些高级策略,请参阅cookbook

警告

从版本0.15.0开始,pandas需要PyTables> = 3.0.0。使用先前版本的pandas / PyTables> = 2.3编写的存储是完全兼容的(这是以前的最小PyTables所需的版本)。

警告

有一个PyTables索引错误,当使用索引查询存储时可能会出现。如果您看到返回的结果子集,请升级到PyTables> = 3.2。以前创建的商店将需要使用更新的版本重写。

警告

从版本0.17.0起,HDFStore在默认情况下不会删除具有所有缺失值的行。以前,如果缺少所有值(索引除外),则HDFStore将不会将这些行写入磁盘。

In [287]: store = pd.HDFStore('store.h5')

In [288]: print(store)
<class 'pandas.io.pytables.HDFStore'>
File path: store.h5
Empty

对象可以写入文件,就像将键值对添加到dict中一样:

In [289]: np.random.seed(1234)

In [290]: index = pd.date_range('1/1/2000', periods=8)

In [291]: s = pd.Series(randn(5), index=['a', 'b', 'c', 'd', 'e'])

In [292]: df = pd.DataFrame(randn(8, 3), index=index,
   .....:                   columns=['A', 'B', 'C'])
   .....: 

In [293]: wp = pd.Panel(randn(2, 5, 4), items=['Item1', 'Item2'],
   .....:               major_axis=pd.date_range('1/1/2000', periods=5),
   .....:               minor_axis=['A', 'B', 'C', 'D'])
   .....: 

# store.put('s', s) is an equivalent method
In [294]: store['s'] = s

In [295]: store['df'] = df

In [296]: store['wp'] = wp

# the type of stored data
In [297]: store.root.wp._v_attrs.pandas_type
Out[297]: 'wide'

In [298]: store
Out[298]: 
<class 'pandas.io.pytables.HDFStore'>
File path: store.h5
/df            frame        (shape->[8,3])  
/s             series       (shape->[5])    
/wp            wide         (shape->[2,5,4])

在当前或以后的Python会话中,您可以检索存储的对象:

# store.get('df') is an equivalent method
In [299]: store['df']
Out[299]: 
                   A         B         C
2000-01-01  0.887163  0.859588 -0.636524
2000-01-02  0.015696 -2.242685  1.150036
2000-01-03  0.991946  0.953324 -2.021255
2000-01-04 -0.334077  0.002118  0.405453
2000-01-05  0.289092  1.321158 -1.546906
2000-01-06 -0.202646 -0.655969  0.193421
2000-01-07  0.553439  1.318152 -0.469305
2000-01-08  0.675554 -1.817027 -0.183109

# dotted (attribute) access provides get as well
In [300]: store.df
Out[300]: 
                   A         B         C
2000-01-01  0.887163  0.859588 -0.636524
2000-01-02  0.015696 -2.242685  1.150036
2000-01-03  0.991946  0.953324 -2.021255
2000-01-04 -0.334077  0.002118  0.405453
2000-01-05  0.289092  1.321158 -1.546906
2000-01-06 -0.202646 -0.655969  0.193421
2000-01-07  0.553439  1.318152 -0.469305
2000-01-08  0.675554 -1.817027 -0.183109

删除由键指定的对象

# store.remove('wp') is an equivalent method
In [301]: del store['wp']

In [302]: store
Out[302]: 
<class 'pandas.io.pytables.HDFStore'>
File path: store.h5
/df            frame        (shape->[8,3])
/s             series       (shape->[5])  

关闭store对象,上下文管理器

In [303]: store.close()

In [304]: store
Out[304]: 
<class 'pandas.io.pytables.HDFStore'>
File path: store.h5
File is CLOSED

In [305]: store.is_open
Out[305]: False

# Working with, and automatically closing the store with the context
# manager
In [306]: with pd.HDFStore('store.h5') as store:
   .....:     store.keys()
   .....: 

Read/Write API

HDFStore supports an top-level API using read_hdf for reading and to_hdf for writing, similar to how read_csv and to_csv work. (新的0.11.0)

In [307]: df_tl = pd.DataFrame(dict(A=list(range(5)), B=list(range(5))))

In [308]: df_tl.to_hdf('store_tl.h5','table',append=True)

In [309]: pd.read_hdf('store_tl.h5', 'table', where = ['index>2'])
Out[309]: 
   A  B
3  3  3
4  4  4

从0.17.0版本开始,HDFStore将不再删除默认情况下都缺失的行。可以通过设置dropna=True来启用此行为。

In [310]: df_with_missing = pd.DataFrame({'col1':[0, np.nan, 2],
   .....:                                 'col2':[1, np.nan, np.nan]})
   .....: 

In [311]: df_with_missing
Out[311]: 
   col1  col2
0   0.0   1.0
1   NaN   NaN
2   2.0   NaN

In [312]: df_with_missing.to_hdf('file.h5', 'df_with_missing',
   .....:                         format = 'table', mode='w')
   .....: 

In [313]: pd.read_hdf('file.h5', 'df_with_missing')
Out[313]: 
   col1  col2
0   0.0   1.0
1   NaN   NaN
2   2.0   NaN

In [314]: df_with_missing.to_hdf('file.h5', 'df_with_missing',
   .....:                         format = 'table', mode='w', dropna=True)
   .....: 

In [315]: pd.read_hdf('file.h5', 'df_with_missing')
Out[315]: 
   col1  col2
0   0.0   1.0
2   2.0   NaN

对于Panel的长轴也是如此:

In [316]: matrix = [[[np.nan, np.nan, np.nan],[1,np.nan,np.nan]],
   .....:        [[np.nan, np.nan, np.nan], [np.nan,5,6]],
   .....:        [[np.nan, np.nan, np.nan],[np.nan,3,np.nan]]]
   .....: 

In [317]: panel_with_major_axis_all_missing = pd.Panel(matrix,
   .....:         items=['Item1', 'Item2','Item3'],
   .....:         major_axis=[1,2],
   .....:         minor_axis=['A', 'B', 'C'])
   .....: 

In [318]: panel_with_major_axis_all_missing
Out[318]: 
<class 'pandas.core.panel.Panel'>
Dimensions: 3 (items) x 2 (major_axis) x 3 (minor_axis)
Items axis: Item1 to Item3
Major_axis axis: 1 to 2
Minor_axis axis: A to C

In [319]: panel_with_major_axis_all_missing.to_hdf('file.h5', 'panel',
   .....:                                         dropna = True,
   .....:                                         format='table',
   .....:                                         mode='w')
   .....: 

In [320]: reloaded = pd.read_hdf('file.h5', 'panel')

In [321]: reloaded
Out[321]: 
<class 'pandas.core.panel.Panel'>
Dimensions: 3 (items) x 1 (major_axis) x 3 (minor_axis)
Items axis: Item1 to Item3
Major_axis axis: 2 to 2
Minor_axis axis: A to C

Fixed Format

注意

这是Storer格式之前的0.13.0。

以上示例显示使用put进行存储,其以固定阵列格式(称为fixed格式)将HDF5写入PyTables这些类型的存储是不是可写的一次写入(虽然你可以简单地删除它们和重写)。它们也不是可查询的;它们必须全部检索。它们也不支持具有非唯一列名的数据帧。fixed格式存储提供非常快的写入和稍微快于table存储的读取。当使用putto_hdfformat='fixed'format='f'

警告

如果您尝试使用where检索,则fixed格式将产生TypeError

pd.DataFrame(randn(10,2)).to_hdf('test_fixed.h5','df')

pd.read_hdf('test_fixed.h5','df',where='index>5')
TypeError: cannot pass a where specification when reading a fixed format.
           this store must be selected in its entirety

Table Format

HDFStore支持磁盘上的另一个PyTables格式,table格式。概念上,table的形状非常像DataFrame,具有行和列。可以在相同会话或其他会话中附加table此外,支持删除和查询类型操作。This format is specified by format='table' or format='t' to append or put or to_hdf

版本0.13中的新功能。

此格式可以设置为默认情况下启用put/append/to_hdf的选项pd.set_option('io.hdf.default_format','table')table格式保存。

In [322]: store = pd.HDFStore('store.h5')

In [323]: df1 = df[0:4]

In [324]: df2 = df[4:]

# append data (creates a table automatically)
In [325]: store.append('df', df1)

In [326]: store.append('df', df2)

In [327]: store
Out[327]: 
<class 'pandas.io.pytables.HDFStore'>
File path: store.h5
/df            frame_table  (typ->appendable,nrows->8,ncols->3,indexers->[index])

# select the entire object
In [328]: store.select('df')
Out[328]: 
                   A         B         C
2000-01-01  0.887163  0.859588 -0.636524
2000-01-02  0.015696 -2.242685  1.150036
2000-01-03  0.991946  0.953324 -2.021255
2000-01-04 -0.334077  0.002118  0.405453
2000-01-05  0.289092  1.321158 -1.546906
2000-01-06 -0.202646 -0.655969  0.193421
2000-01-07  0.553439  1.318152 -0.469305
2000-01-08  0.675554 -1.817027 -0.183109

# the type of stored data
In [329]: store.root.df._v_attrs.pandas_type
Out[329]: 'frame_table'

注意

您还可以通过将format='table'format='t'传递到put来创建table

Hierarchical Keys

商店的键可以指定为字符串。这些可以是层次化路径名格式(例如foo/bar/bah),它将生成子存储的层次结构(或PyTables中的Groups) 。键可以指定前面的'/',并且是绝对的(例如'foo'是指'/ foo')。删除操作可以删除子存储和BELOW中的所有内容,因此请小心

In [330]: store.put('foo/bar/bah', df)

In [331]: store.append('food/orange', df)

In [332]: store.append('food/apple',  df)

In [333]: store
Out[333]: 
<class 'pandas.io.pytables.HDFStore'>
File path: store.h5
/df                     frame_table  (typ->appendable,nrows->8,ncols->3,indexers->[index])
/foo/bar/bah            frame        (shape->[8,3])                                       
/food/apple             frame_table  (typ->appendable,nrows->8,ncols->3,indexers->[index])
/food/orange            frame_table  (typ->appendable,nrows->8,ncols->3,indexers->[index])

# a list of keys are returned
In [334]: store.keys()
Out[334]: ['/df', '/food/apple', '/food/orange', '/foo/bar/bah']

# remove all nodes under this level
In [335]: store.remove('food')

In [336]: store
Out[336]: 
<class 'pandas.io.pytables.HDFStore'>
File path: store.h5
/df                     frame_table  (typ->appendable,nrows->8,ncols->3,indexers->[index])
/foo/bar/bah            frame        (shape->[8,3])                                       

警告

分层密钥不能被检索为如上所述的存储在根节点下的项目的点(属性)访问。

In [8]: store.foo.bar.bah
AttributeError: 'HDFStore' object has no attribute 'foo'

# you can directly access the actual PyTables node but using the root node
In [9]: store.root.foo.bar.bah
Out[9]:
/foo/bar/bah (Group) ''
  children := ['block0_items' (Array), 'block0_values' (Array), 'axis0' (Array), 'axis1' (Array)]

相反,使用显式字符串为基础的键

In [337]: store['foo/bar/bah']
Out[337]: 
                   A         B         C
2000-01-01  0.887163  0.859588 -0.636524
2000-01-02  0.015696 -2.242685  1.150036
2000-01-03  0.991946  0.953324 -2.021255
2000-01-04 -0.334077  0.002118  0.405453
2000-01-05  0.289092  1.321158 -1.546906
2000-01-06 -0.202646 -0.655969  0.193421
2000-01-07  0.553439  1.318152 -0.469305
2000-01-08  0.675554 -1.817027 -0.183109

Storing Types

Storing Mixed Types in a Table

支持存储混合数据类型。字符串使用附加列的最大大小存储为固定宽度。随后尝试追加更长的字符串将产生ValueError

min_itemsize = {`values`: size}作为参数传递将为字符串列设置较大的最小值。存储浮点, 字符串, int, bools, datetime64 t0>目前支持。对于字符串列,传递nan_rep = 'nan'可以更改磁盘上的默认nan表示转换为/从np.nan),默认为nan

In [338]: df_mixed = pd.DataFrame({ 'A' : randn(8),
   .....:                           'B' : randn(8),
   .....:                           'C' : np.array(randn(8),dtype='float32'),
   .....:                           'string' :'string',
   .....:                           'int' : 1,
   .....:                           'bool' : True,
   .....:                           'datetime64' : pd.Timestamp('20010102')},
   .....:                         index=list(range(8)))
   .....: 

In [339]: df_mixed.ix[3:5,['A', 'B', 'string', 'datetime64']] = np.nan

In [340]: store.append('df_mixed', df_mixed, min_itemsize = {'values': 50})

In [341]: df_mixed1 = store.select('df_mixed')

In [342]: df_mixed1
Out[342]: 
          A         B         C  bool datetime64  int  string
0  0.704721 -1.152659 -0.430096  True 2001-01-02    1  string
1 -0.785435  0.631979  0.767369  True 2001-01-02    1  string
2  0.462060  0.039513  0.984920  True 2001-01-02    1  string
3       NaN       NaN  0.270836  True        NaT    1     NaN
4       NaN       NaN  1.391986  True        NaT    1     NaN
5       NaN       NaN  0.079842  True        NaT    1     NaN
6  2.007843  0.152631 -0.399965  True 2001-01-02    1  string
7  0.226963  0.164530 -1.027851  True 2001-01-02    1  string

In [343]: df_mixed1.get_dtype_counts()
Out[343]: 
bool              1
datetime64[ns]    1
float32           1
float64           2
int64             1
object            1
dtype: int64

# we have provided a minimum string column size
In [344]: store.root.df_mixed.table
Out[344]: 
/df_mixed/table (Table(8,)) ''
  description := {
  "index": Int64Col(shape=(), dflt=0, pos=0),
  "values_block_0": Float64Col(shape=(2,), dflt=0.0, pos=1),
  "values_block_1": Float32Col(shape=(1,), dflt=0.0, pos=2),
  "values_block_2": Int64Col(shape=(1,), dflt=0, pos=3),
  "values_block_3": Int64Col(shape=(1,), dflt=0, pos=4),
  "values_block_4": BoolCol(shape=(1,), dflt=False, pos=5),
  "values_block_5": StringCol(itemsize=50, shape=(1,), dflt='', pos=6)}
  byteorder := 'little'
  chunkshape := (689,)
  autoindex := True
  colindexes := {
    "index": Index(6, medium, shuffle, zlib(1)).is_csi=False}

Storing Multi-Index DataFrames

将多索引数据帧存储为表非常类似于从同构索引DataFrames存储/选择。

In [345]: index = pd.MultiIndex(levels=[['foo', 'bar', 'baz', 'qux'],
   .....:                               ['one', 'two', 'three']],
   .....:                       labels=[[0, 0, 0, 1, 1, 2, 2, 3, 3, 3],
   .....:                               [0, 1, 2, 0, 1, 1, 2, 0, 1, 2]],
   .....:                       names=['foo', 'bar'])
   .....: 

In [346]: df_mi = pd.DataFrame(np.random.randn(10, 3), index=index,
   .....:                      columns=['A', 'B', 'C'])
   .....: 

In [347]: df_mi
Out[347]: 
                  A         B         C
foo bar                                
foo one   -0.584718  0.816594 -0.081947
    two   -0.344766  0.528288 -1.068989
    three -0.511881  0.291205  0.566534
bar one    0.503592  0.285296  0.484288
    two    1.363482 -0.781105 -0.468018
baz two    1.224574 -1.281108  0.875476
    three -1.710715 -0.450765  0.749164
qux one   -0.203933 -0.182175  0.680656
    two   -1.818499  0.047072  0.394844
    three -0.248432 -0.617707 -0.682884

In [348]: store.append('df_mi',df_mi)

In [349]: store.select('df_mi')
Out[349]: 
                  A         B         C
foo bar                                
foo one   -0.584718  0.816594 -0.081947
    two   -0.344766  0.528288 -1.068989
    three -0.511881  0.291205  0.566534
bar one    0.503592  0.285296  0.484288
    two    1.363482 -0.781105 -0.468018
baz two    1.224574 -1.281108  0.875476
    three -1.710715 -0.450765  0.749164
qux one   -0.203933 -0.182175  0.680656
    two   -1.818499  0.047072  0.394844
    three -0.248432 -0.617707 -0.682884

# the levels are automatically included as data columns
In [350]: store.select('df_mi', 'foo=bar')
Out[350]: 
                A         B         C
foo bar                              
bar one  0.503592  0.285296  0.484288
    two  1.363482 -0.781105 -0.468018

Querying

Querying a Table

警告

此查询功能在0.13.0中实质性更改。如果其不是字符串类型,则接受来自先前版本的查询(使用DeprecationWarning)。

selectdelete操作具有可选择的标准,可以指定仅选择/删除数据的子集。这允许有一个非常大的磁盘表,并且只检索一部分数据。

使用Term类指定查询作为布尔表达式。

  • indexcolumns是DataFrame的支持索引器
  • major_axisminor_axisitems是面板的支持索引器
  • 如果指定data_columns,这些可以用作附加索引器

有效的比较运算符为:

=, ==, !=, &gt;, / t5> &lt;, &lt; =

有效的布尔表达式结合:

  • |:或
  • &:和
  • (and):用于分组

这些规则类似于在pandas中用于索引的布尔表达式。

注意

  • =将自动展开为比较运算符==
  • ~是非运算符,但只能在非常有限的情况下使用
  • 如果传递表达式的列表/元组,则它们将通过&组合

以下是有效的表达式:

  • 'index>=date'
  • “columns = ['A', 'D']”
  • "columns in ['A', 'D']"
  • 'columns=A'
  • 'columns==A'
  • "~(columns=['A','B'])"
  • 'index&gt; df.index [3] &amp; string =“bar”'
  • '(索引&gt; df.index [3] &amp; 索引 string =“bar”'
  • "ts>=Timestamp('2012-02-01')"
  • "major_axis>=20130101"

indexers位于子表达式的左侧:

columnsmajor_axists

子表达式的右侧(在比较运算符之后)可以是:

  • 将被评估的函数,例如。 Timestamp('2012-02-01')
  • 字符串,例如"bar"
  • 日期样。 20130101"20130101"
  • 列表,例如。 "['A','B']"
  • 在本地名称空间中定义的变量,例如。 date

注意

不推荐通过将字符串插入查询表达式来将字符串传递给查询。只需将感兴趣的字符串分配给变量,并在表达式中使用该变量。例如,这样做

string = "HolyMoly'"
store.select('df', 'index == string')

而不是这个

string = "HolyMoly'"
store.select('df',  'index == %s' % string)

后者将工作,并会引发SyntaxError。注意,在string变量中有一个单引号后跟一个双引号。

如果必须插值,请使用'%r'格式说明符

store.select('df', 'index == %r' % string)

其将引用string

这里有些例子:

In [351]: dfq = pd.DataFrame(randn(10,4),columns=list('ABCD'),index=pd.date_range('20130101',periods=10))

In [352]: store.append('dfq',dfq,format='table',data_columns=True)

使用布尔表达式,具有行内函数评估。

In [353]: store.select('dfq',"index>pd.Timestamp('20130104') & columns=['A', 'B']")
Out[353]: 
                   A         B
2013-01-05  1.210384  0.797435
2013-01-06 -0.850346  1.176812
2013-01-07  0.984188 -0.121728
2013-01-08  0.796595 -0.474021
2013-01-09 -0.804834 -2.123620
2013-01-10  0.334198  0.536784

使用和内联列引用

In [354]: store.select('dfq',where="A>0 or C>0")
Out[354]: 
                   A         B         C         D
2013-01-01  0.436258 -1.703013  0.393711 -0.479324
2013-01-02 -0.299016  0.694103  0.678630  0.239556
2013-01-03  0.151227  0.816127  1.893534  0.639633
2013-01-04 -0.962029 -2.085266  1.930247 -1.735349
2013-01-05  1.210384  0.797435 -0.379811  0.702562
2013-01-07  0.984188 -0.121728  2.365769  0.496143
2013-01-08  0.796595 -0.474021 -0.056696  1.357797
2013-01-10  0.334198  0.536784 -0.743830 -0.320204

也与小组一起工作。

In [355]: store.append('wp',wp)

In [356]: store
Out[356]: 
<class 'pandas.io.pytables.HDFStore'>
File path: store.h5
/df                     frame_table  (typ->appendable,nrows->8,ncols->3,indexers->[index])                     
/df_mi                  frame_table  (typ->appendable_multi,nrows->10,ncols->5,indexers->[index],dc->[bar,foo])
/df_mixed               frame_table  (typ->appendable,nrows->8,ncols->7,indexers->[index])                     
/dfq                    frame_table  (typ->appendable,nrows->10,ncols->4,indexers->[index],dc->[A,B,C,D])      
/foo/bar/bah            frame        (shape->[8,3])                                                            
/wp                     wide_table   (typ->appendable,nrows->20,ncols->2,indexers->[major_axis,minor_axis])    

In [357]: store.select('wp', "major_axis>pd.Timestamp('20000102') & minor_axis=['A', 'B']")
Out[357]: 
<class 'pandas.core.panel.Panel'>
Dimensions: 2 (items) x 3 (major_axis) x 2 (minor_axis)
Items axis: Item1 to Item2
Major_axis axis: 2000-01-03 00:00:00 to 2000-01-05 00:00:00
Minor_axis axis: A to B

可以提供columns关键字来选择要返回的列的列表,这相当于传递'columns=list_of_columns_to_filter'

In [358]: store.select('df', "columns=['A', 'B']")
Out[358]: 
                   A         B
2000-01-01  0.887163  0.859588
2000-01-02  0.015696 -2.242685
2000-01-03  0.991946  0.953324
2000-01-04 -0.334077  0.002118
2000-01-05  0.289092  1.321158
2000-01-06 -0.202646 -0.655969
2000-01-07  0.553439  1.318152
2000-01-08  0.675554 -1.817027

可以指定startstop参数来限制总搜索空间。这些是根据表中的总行数。

# this is effectively what the storage of a Panel looks like
In [359]: wp.to_frame()
Out[359]: 
                     Item1     Item2
major      minor                    
2000-01-01 A      1.058969  0.215269
           B     -0.397840  0.841009
           C      0.337438 -1.445810
           D      1.047579 -1.401973
2000-01-02 A      1.045938 -0.100918
           B      0.863717 -0.548242
           C     -0.122092 -0.144620
...                    ...       ...
2000-01-04 B      0.036142  0.307969
           C     -2.074978 -0.208499
           D      0.247792  1.033801
2000-01-05 A     -0.897157 -2.400454
           B     -0.136795  2.030604
           C      0.018289 -1.142631
           D      0.755414  0.211883

[20 rows x 2 columns]

# limiting the search
In [360]: store.select('wp',"major_axis>20000102 & minor_axis=['A','B']",
   .....:              start=0, stop=10)
   .....: 
Out[360]: 
<class 'pandas.core.panel.Panel'>
Dimensions: 2 (items) x 1 (major_axis) x 2 (minor_axis)
Items axis: Item1 to Item2
Major_axis axis: 2000-01-03 00:00:00 to 2000-01-03 00:00:00
Minor_axis axis: A to B

注意

如果查询表达式具有未知的变量引用,则select将引发ValueError通常这意味着您试图在而不是数据列的列上选择。

如果查询表达式无效,则select会引发SyntaxError

Using timedelta64[ns]

版本0.13中的新功能。

从0.13.0开始,您可以使用timedelta64[ns]类型存储和查询。Terms can be specified in the format: <float>(<unit>), where float may be signed (and fractional), and unit can be D,s,ms,us,ns for the timedelta. 这里有一个例子:

In [361]: from datetime import timedelta

In [362]: dftd = pd.DataFrame(dict(A = pd.Timestamp('20130101'), B = [ pd.Timestamp('20130101') + timedelta(days=i,seconds=10) for i in range(10) ]))

In [363]: dftd['C'] = dftd['A']-dftd['B']

In [364]: dftd
Out[364]: 
           A                   B                  C
0 2013-01-01 2013-01-01 00:00:10  -1 days +23:59:50
1 2013-01-01 2013-01-02 00:00:10  -2 days +23:59:50
2 2013-01-01 2013-01-03 00:00:10  -3 days +23:59:50
3 2013-01-01 2013-01-04 00:00:10  -4 days +23:59:50
4 2013-01-01 2013-01-05 00:00:10  -5 days +23:59:50
5 2013-01-01 2013-01-06 00:00:10  -6 days +23:59:50
6 2013-01-01 2013-01-07 00:00:10  -7 days +23:59:50
7 2013-01-01 2013-01-08 00:00:10  -8 days +23:59:50
8 2013-01-01 2013-01-09 00:00:10  -9 days +23:59:50
9 2013-01-01 2013-01-10 00:00:10 -10 days +23:59:50

In [365]: store.append('dftd',dftd,data_columns=True)

In [366]: store.select('dftd',"C<'-3.5D'")
Out[366]: 
           A                   B                  C
4 2013-01-01 2013-01-05 00:00:10  -5 days +23:59:50
5 2013-01-01 2013-01-06 00:00:10  -6 days +23:59:50
6 2013-01-01 2013-01-07 00:00:10  -7 days +23:59:50
7 2013-01-01 2013-01-08 00:00:10  -8 days +23:59:50
8 2013-01-01 2013-01-09 00:00:10  -9 days +23:59:50
9 2013-01-01 2013-01-10 00:00:10 -10 days +23:59:50

Indexing

在数据已经在表中之后(在append/put操作之后),可以使用create_table_index创建/修改表的索引。鼓励创建表索引高度当您使用索引维度作为whereselect时,这将加快查询速度。

注意

在索引表和您指定的任何数据列上自动创建索引(起始0.10.1)。可以通过将index=False传递给append来关闭此行为。

# we have automagically already created an index (in the first section)
In [367]: i = store.root.df.table.cols.index.index

In [368]: i.optlevel, i.kind
Out[368]: (6, 'medium')

# change an index by passing new parameters
In [369]: store.create_table_index('df', optlevel=9, kind='full')

In [370]: i = store.root.df.table.cols.index.index

In [371]: i.optlevel, i.kind
Out[371]: (9, 'full')

通常当将大量数据附加到内存时,关闭每个附加项的索引创建是有用的,然后在结束时重新创建。

In [372]: df_1 = pd.DataFrame(randn(10,2),columns=list('AB'))

In [373]: df_2 = pd.DataFrame(randn(10,2),columns=list('AB'))

In [374]: st = pd.HDFStore('appends.h5',mode='w')

In [375]: st.append('df', df_1, data_columns=['B'], index=False)

In [376]: st.append('df', df_2, data_columns=['B'], index=False)

In [377]: st.get_storer('df').table
Out[377]: 
/df/table (Table(20,)) ''
  description := {
  "index": Int64Col(shape=(), dflt=0, pos=0),
  "values_block_0": Float64Col(shape=(1,), dflt=0.0, pos=1),
  "B": Float64Col(shape=(), dflt=0.0, pos=2)}
  byteorder := 'little'
  chunkshape := (2730,)

然后在完成附加时创建索引。

In [378]: st.create_table_index('df', columns=['B'], optlevel=9, kind='full')

In [379]: st.get_storer('df').table
Out[379]: 
/df/table (Table(20,)) ''
  description := {
  "index": Int64Col(shape=(), dflt=0, pos=0),
  "values_block_0": Float64Col(shape=(1,), dflt=0.0, pos=1),
  "B": Float64Col(shape=(), dflt=0.0, pos=2)}
  byteorder := 'little'
  chunkshape := (2730,)
  autoindex := True
  colindexes := {
    "B": Index(9, full, shuffle, zlib(1)).is_csi=True}

In [380]: st.close()

有关如何在现有存储上创建完全排序索引(CSI)的信息,请参见此处

Query via Data Columns

您可以指定(和建立索引)您希望能够执行查询的某些列(除了可以始终查询的可索引的列)。例如,您想要执行此常见操作,磁盘上,并只返回匹配此查询的框架。您可以指定data_columns = True以强制所有列为data_columns

In [381]: df_dc = df.copy()

In [382]: df_dc['string'] = 'foo'

In [383]: df_dc.ix[4:6,'string'] = np.nan

In [384]: df_dc.ix[7:9,'string'] = 'bar'

In [385]: df_dc['string2'] = 'cool'

In [386]: df_dc.ix[1:3,['B','C']] = 1.0

In [387]: df_dc
Out[387]: 
                   A         B         C string string2
2000-01-01  0.887163  0.859588 -0.636524    foo    cool
2000-01-02  0.015696  1.000000  1.000000    foo    cool
2000-01-03  0.991946  1.000000  1.000000    foo    cool
2000-01-04 -0.334077  0.002118  0.405453    foo    cool
2000-01-05  0.289092  1.321158 -1.546906    NaN    cool
2000-01-06 -0.202646 -0.655969  0.193421    NaN    cool
2000-01-07  0.553439  1.318152 -0.469305    foo    cool
2000-01-08  0.675554 -1.817027 -0.183109    bar    cool

# on-disk operations
In [388]: store.append('df_dc', df_dc, data_columns = ['B', 'C', 'string', 'string2'])

In [389]: store.select('df_dc', [ pd.Term('B>0') ])
Out[389]: 
                   A         B         C string string2
2000-01-01  0.887163  0.859588 -0.636524    foo    cool
2000-01-02  0.015696  1.000000  1.000000    foo    cool
2000-01-03  0.991946  1.000000  1.000000    foo    cool
2000-01-04 -0.334077  0.002118  0.405453    foo    cool
2000-01-05  0.289092  1.321158 -1.546906    NaN    cool
2000-01-07  0.553439  1.318152 -0.469305    foo    cool

# getting creative
In [390]: store.select('df_dc', 'B > 0 & C > 0 & string == foo')
Out[390]: 
                   A         B         C string string2
2000-01-02  0.015696  1.000000  1.000000    foo    cool
2000-01-03  0.991946  1.000000  1.000000    foo    cool
2000-01-04 -0.334077  0.002118  0.405453    foo    cool

# this is in-memory version of this type of selection
In [391]: df_dc[(df_dc.B > 0) & (df_dc.C > 0) & (df_dc.string == 'foo')]
Out[391]: 
                   A         B         C string string2
2000-01-02  0.015696  1.000000  1.000000    foo    cool
2000-01-03  0.991946  1.000000  1.000000    foo    cool
2000-01-04 -0.334077  0.002118  0.405453    foo    cool

# we have automagically created this index and the B/C/string/string2
# columns are stored separately as ``PyTables`` columns
In [392]: store.root.df_dc.table
Out[392]: 
/df_dc/table (Table(8,)) ''
  description := {
  "index": Int64Col(shape=(), dflt=0, pos=0),
  "values_block_0": Float64Col(shape=(1,), dflt=0.0, pos=1),
  "B": Float64Col(shape=(), dflt=0.0, pos=2),
  "C": Float64Col(shape=(), dflt=0.0, pos=3),
  "string": StringCol(itemsize=3, shape=(), dflt='', pos=4),
  "string2": StringCol(itemsize=4, shape=(), dflt='', pos=5)}
  byteorder := 'little'
  chunkshape := (1680,)
  autoindex := True
  colindexes := {
    "index": Index(6, medium, shuffle, zlib(1)).is_csi=False,
    "C": Index(6, medium, shuffle, zlib(1)).is_csi=False,
    "B": Index(6, medium, shuffle, zlib(1)).is_csi=False,
    "string2": Index(6, medium, shuffle, zlib(1)).is_csi=False,
    "string": Index(6, medium, shuffle, zlib(1)).is_csi=False}

通过将大量列置入数据列中,会有一些性能下降,因此由用户指定这些列。此外,你不能在第一次append / put操作后更改数据列(也不能索引)(当然你可以简单地读入数据并创建一个新表!)

Iterator

0.11.0开始,您可以传递iterator=Truechunksize=number_in_a_chunkselectselect_as_multiple在结果上返回一个迭代器。默认值是在一个块中返回的50,000行。

In [393]: for df in store.select('df', chunksize=3):
   .....:    print(df)
   .....: 
                   A         B         C
2000-01-01  0.887163  0.859588 -0.636524
2000-01-02  0.015696 -2.242685  1.150036
2000-01-03  0.991946  0.953324 -2.021255
                   A         B         C
2000-01-04 -0.334077  0.002118  0.405453
2000-01-05  0.289092  1.321158 -1.546906
2000-01-06 -0.202646 -0.655969  0.193421
                   A         B         C
2000-01-07  0.553439  1.318152 -0.469305
2000-01-08  0.675554 -1.817027 -0.183109

注意

版本0.12.0中的新功能。

您还可以使用具有read_hdf的迭代器,它将打开,然后在完成迭代后自动关闭存储。

for df in pd.read_hdf('store.h5','df', chunksize=3):
    print(df)

请注意,chunksize关键字适用于行。因此,如果您正在执行查询,那么chunksize将细分表中的所有行并应用查询,在可能不等大小的块上返回一个迭代器。

下面是一个生成查询并使用它来创建大小相等的返回块的方法。

In [394]: dfeq = pd.DataFrame({'number': np.arange(1,11)})

In [395]: dfeq
Out[395]: 
   number
0       1
1       2
2       3
3       4
4       5
5       6
6       7
7       8
8       9
9      10

In [396]: store.append('dfeq', dfeq, data_columns=['number'])

In [397]: def chunks(l, n):
   .....:      return [l[i:i+n] for i in range(0, len(l), n)]
   .....: 

In [398]: evens = [2,4,6,8,10]

In [399]: coordinates = store.select_as_coordinates('dfeq','number=evens')

In [400]: for c in chunks(coordinates, 2):
   .....:      print store.select('dfeq',where=c)
   .....: 
   number
1       2
3       4
   number
5       6
7       8
   number
9      10

Advanced Queries

Select a Single Column

要检索单个可索引或数据列,请使用方法select_column例如,这将使您能够非常快地获取索引。这些返回结果的Series,由行号索引。它们目前不接受where选择器。

In [401]: store.select_column('df_dc', 'index')
Out[401]: 
0   2000-01-01
1   2000-01-02
2   2000-01-03
3   2000-01-04
4   2000-01-05
5   2000-01-06
6   2000-01-07
7   2000-01-08
Name: index, dtype: datetime64[ns]

In [402]: store.select_column('df_dc', 'string')
Out[402]: 
0    foo
1    foo
2    foo
3    foo
4    NaN
5    NaN
6    foo
7    bar
Name: string, dtype: object
Selecting coordinates

有时您想要获取查询的坐标(a.k.a索引位置)。这将返回结果位置的Int64Index这些坐标也可以传递到后续的where操作。

In [403]: df_coord = pd.DataFrame(np.random.randn(1000,2),index=pd.date_range('20000101',periods=1000))

In [404]: store.append('df_coord',df_coord)

In [405]: c = store.select_as_coordinates('df_coord','index>20020101')

In [406]: c.summary()
Out[406]: u'Int64Index: 268 entries, 732 to 999'

In [407]: store.select('df_coord',where=c)
Out[407]: 
                   0         1
2002-01-02 -0.178266 -0.064638
2002-01-03 -1.204956 -3.880898
2002-01-04  0.974470  0.415160
2002-01-05  1.751967  0.485011
2002-01-06 -0.170894  0.748870
2002-01-07  0.629793  0.811053
2002-01-08  2.133776  0.238459
...              ...       ...
2002-09-20 -0.181434  0.612399
2002-09-21 -0.763324 -0.354962
2002-09-22 -0.261776  0.812126
2002-09-23  0.482615 -0.886512
2002-09-24 -0.037757 -0.562953
2002-09-25  0.897706  0.383232
2002-09-26 -1.324806  1.139269

[268 rows x 2 columns]
Selecting using a where mask

有时,您的查询可能涉及创建要选择的行的列表。通常,此mask将是来自索引操作的结果index此示例选择datetimeindex的月份为5。

In [408]: df_mask = pd.DataFrame(np.random.randn(1000,2),index=pd.date_range('20000101',periods=1000))

In [409]: store.append('df_mask',df_mask)

In [410]: c = store.select_column('df_mask','index')

In [411]: where = c[pd.DatetimeIndex(c).month==5].index

In [412]: store.select('df_mask',where=where)
Out[412]: 
                   0         1
2000-05-01 -1.006245 -0.616759
2000-05-02  0.218940  0.717838
2000-05-03  0.013333  1.348060
2000-05-04  0.662176 -1.050645
2000-05-05 -1.034870 -0.243242
2000-05-06 -0.753366 -1.454329
2000-05-07 -1.022920 -0.476989
...              ...       ...
2002-05-25 -0.509090 -0.389376
2002-05-26  0.150674  1.164337
2002-05-27 -0.332944  0.115181
2002-05-28 -1.048127 -0.605733
2002-05-29  1.418754 -0.442835
2002-05-30 -0.433200  0.835001
2002-05-31 -1.041278  1.401811

[93 rows x 2 columns]
Storer Object

如果要检查存储的对象,请通过get_storer检索。你可以使用这个程序来说明获取对象中的行数。

In [413]: store.get_storer('df_dc').nrows
Out[413]: 8

Multiple Table Queries

0.10.1中的新增功能是方法append_to_multipleselect_as_multiple,可以一次执行从多个表中追加/选择。想法是有一个表(称为选择器表),您索引最多/所有的列,并执行您的查询。其他表是具有与选择器表的索引匹配的索引的数据表。然后,您可以对选择器表执行非常快速的查询,但返回大量数据。此方法类似于具有非常宽的表,但是可以实现更高效的查询。

append_to_multiple方法根据d将给定的单个DataFrame拆分为多个表,该字典将表名映射到该表中所需的“列”列表。如果使用None代替列表,则该表将具有给定DataFrame的其余未指定列。参数selector定义哪个表是选择器表(您可以从中进行查询)。参数dropna将从输入DataFrame中删除行以确保表同步。这意味着,如果写入的其中一个表的行完全为np.NaN,那么该行将从所有表中删除。

如果dropna为False,则用户负责同步表格Remember that entirely np.Nan rows are not written to the HDFStore, so if you choose to call dropna=False, some tables may have more rows than others, and therefore select_as_multiple may not work or it may return unexpected results.

In [414]: df_mt = pd.DataFrame(randn(8, 6), index=pd.date_range('1/1/2000', periods=8),
   .....:                                   columns=['A', 'B', 'C', 'D', 'E', 'F'])
   .....: 

In [415]: df_mt['foo'] = 'bar'

In [416]: df_mt.ix[1, ('A', 'B')] = np.nan

# you can also create the tables individually
In [417]: store.append_to_multiple({'df1_mt': ['A', 'B'], 'df2_mt': None },
   .....:                           df_mt, selector='df1_mt')
   .....: 

In [418]: store
Out[418]: 
<class 'pandas.io.pytables.HDFStore'>
File path: store.h5
/df                     frame_table  (typ->appendable,nrows->8,ncols->3,indexers->[index])                         
/df1_mt                 frame_table  (typ->appendable,nrows->8,ncols->2,indexers->[index],dc->[A,B])               
/df2_mt                 frame_table  (typ->appendable,nrows->8,ncols->5,indexers->[index])                         
/df_coord               frame_table  (typ->appendable,nrows->1000,ncols->2,indexers->[index])                      
/df_dc                  frame_table  (typ->appendable,nrows->8,ncols->5,indexers->[index],dc->[B,C,string,string2])
/df_mask                frame_table  (typ->appendable,nrows->1000,ncols->2,indexers->[index])                      
/df_mi                  frame_table  (typ->appendable_multi,nrows->10,ncols->5,indexers->[index],dc->[bar,foo])    
/df_mixed               frame_table  (typ->appendable,nrows->8,ncols->7,indexers->[index])                         
/dfeq                   frame_table  (typ->appendable,nrows->10,ncols->1,indexers->[index],dc->[number])           
/dfq                    frame_table  (typ->appendable,nrows->10,ncols->4,indexers->[index],dc->[A,B,C,D])          
/dftd                   frame_table  (typ->appendable,nrows->10,ncols->3,indexers->[index],dc->[A,B,C])            
/foo/bar/bah            frame        (shape->[8,3])                                                                
/wp                     wide_table   (typ->appendable,nrows->20,ncols->2,indexers->[major_axis,minor_axis])        

# individual tables were created
In [419]: store.select('df1_mt')
Out[419]: 
                   A         B
2000-01-01  0.714697  0.318215
2000-01-02       NaN       NaN
2000-01-03 -0.086919  0.416905
2000-01-04  0.489131 -0.253340
2000-01-05 -0.382952 -0.397373
2000-01-06  0.538116  0.226388
2000-01-07 -2.073479 -0.115926
2000-01-08 -0.695400  0.402493

In [420]: store.select('df2_mt')
Out[420]: 
                   C         D         E         F  foo
2000-01-01  0.607460  0.790907  0.852225  0.096696  bar
2000-01-02  0.811031 -0.356817  1.047085  0.664705  bar
2000-01-03 -0.764381 -0.287229 -0.089351 -1.035115  bar
2000-01-04 -1.948100 -0.116556  0.800597 -0.796154  bar
2000-01-05 -0.717627  0.156995 -0.344718 -0.171208  bar
2000-01-06  1.541729  0.205256  1.998065  0.953591  bar
2000-01-07  1.391070  0.303013  1.093347 -0.101000  bar
2000-01-08 -1.507639  0.089575  0.658822 -1.037627  bar

# as a multiple
In [421]: store.select_as_multiple(['df1_mt', 'df2_mt'], where=['A>0', 'B>0'],
   .....:                           selector = 'df1_mt')
   .....: 
Out[421]: 
                   A         B         C         D         E         F  foo
2000-01-01  0.714697  0.318215  0.607460  0.790907  0.852225  0.096696  bar
2000-01-06  0.538116  0.226388  1.541729  0.205256  1.998065  0.953591  bar

Delete from a Table

您可以通过指定where选择性地从表中删除。在删除行时,了解PyTables通过擦除行,然后移动以下数据删除行很重要。因此,删除可能是一个非常昂贵的操作,具体取决于数据的方向。这在更高维度的物体(PanelPanel4D)中尤其如此。为了获得最佳效果,您需要将要删除的维度作为indexables中的第一个维度。

数据按照indexables的顺序排列(在磁盘上)。这里有一个简单的用例。您存储面板类型数据,日期在major_axis中,而ID在minor_axis中。然后数据交织如下:

应当清楚,对major_axis的删除操作将会相当快速,因为删除了一个块,然后移动以下数据。另一方面,对minor_axis的删除操作将非常昂贵。在这种情况下,使用where选择除缺少的数据之外的所有数据。

# returns the number of rows deleted
In [422]: store.remove('wp', 'major_axis>20000102' )
Out[422]: 12

In [423]: store.select('wp')
Out[423]: 
<class 'pandas.core.panel.Panel'>
Dimensions: 2 (items) x 2 (major_axis) x 4 (minor_axis)
Items axis: Item1 to Item2
Major_axis axis: 2000-01-01 00:00:00 to 2000-01-02 00:00:00
Minor_axis axis: A to D

警告

请注意,h5文件中的HDF5 不会记录空格因此,重复删除(或删除节点)并再次添加,将增加文件大小

重新包装并清除该文件,请使用ptrepack

Notes & Caveats

Compression

PyTables允许压缩存储的数据。这适用于各种商店,而不仅仅是表。

  • 对于压缩级别(1-9,0是无压缩,默认值),传递complevel=int
  • 传递complib=lib其中lib是zlib, bzip2, lzo, 用于您喜欢的压缩库。

HDFStore will use the file based compression scheme if no overriding complib or complevel options are provided. blosc提供非常快速的压缩,是我最常用的。请注意,默认情况下可能不安装lzobzip2(通过Python)。

压缩文件中的所有对象

store_compressed = pd.HDFStore('store_compressed.h5', complevel=9, complib='blosc')

或即时压缩(这只适用于表)。您可以通过传递complevel=0来关闭特定表的文件压缩

store.append('df', df, complib='zlib', complevel=5)

ptrepack

PyTables在写入表之后压缩表时提供更好的写入性能,而不是在开始时打开压缩。您可以使用提供的PyTables实用程序ptrepack此外,ptrepack可以在事实之后更改压缩级别。

ptrepack --chunkshape=auto --propindexes --complevel=9 --complib=blosc in.h5 out.h5

Furthermore ptrepack in.h5 out.h5 will repack the file to allow you to reuse previously deleted space. 或者,可以简单地删除文件并再次写入,或使用copy方法。

Caveats

警告

HDFStore不能写入的线程安全。底层的PyTables只支持并发读取(通过线程或进程)。如果您需要同时读取和写入,则需要在单个进程中在单个线程中将这些操作序列化。否则将损坏您的数据。有关详细信息,请参阅(GH2397)。

  • 如果使用锁来管理多个进程之间的写访问,则可能需要在释放写锁之前使用fsync()为方便起见,您可以使用store.flush(fsync=True)为您执行此操作。
  • 一旦创建了table,它的项(Panel)/列(DataFrame)就是固定的;只能附加完全相同的列
  • 请注意,时区(例如,pytz.timezone('US/Eastern'))在时区版本中不一定相等。因此,如果数据被本地化到HDFStore中使用一个版本的时区库的特定时区,并且数据被更新为另一个版本,则数据将被转换为UTC,因为这些时区不被视为相等。可以使用相同版本的时区库,也可以使用tz_convert更新时区定义。

警告

PyTables将显示NaturalNameWarning自然标识符只包含字母,数字和下划线,且不能以数字开头。其他标识符不能在where子句中使用,通常是一个坏主意。

DataTypes

HDFStore会将对象dtype映射到PyTables底层dtype。这意味着以下类型已知可以工作:

类型 表示缺少的值
浮动:float64, float32, float16 np.nan
整数:int64, int32, int8, uint64,uint32, uint8 t5 >  
布尔  
datetime64[ns] NaT
timedelta64[ns] NaT
分类:见下面部分  
对象:strings np.nan

unicode列不受支持,WILL FAIL

Categorical Data

版本0.15.2中的新功能。

将数据写入到包含category dtype的HDFStore中已在0.15.2中实现。查询的工作方式与它是一个对象数组相同。但是,category类型化数据以更有效的方式存储。

In [424]: dfcat = pd.DataFrame({ 'A' : pd.Series(list('aabbcdba')).astype('category'),
   .....:                        'B' : np.random.randn(8) })
   .....: 

In [425]: dfcat
Out[425]: 
   A         B
0  a  0.603273
1  a  0.262554
2  b -0.979586
3  b  2.132387
4  c  0.892485
5  d  1.996474
6  b  0.231425
7  a  0.980070

In [426]: dfcat.dtypes
Out[426]: 
A    category
B     float64
dtype: object

In [427]: cstore = pd.HDFStore('cats.h5', mode='w')

In [428]: cstore.append('dfcat', dfcat, format='table', data_columns=['A'])

In [429]: result = cstore.select('dfcat', where="A in ['b','c']")

In [430]: result
Out[430]: 
   A         B
2  b -0.979586
3  b  2.132387
4  c  0.892485
6  b  0.231425

In [431]: result.dtypes
Out[431]: 
A    category
B     float64
dtype: object

警告

The format of the Categorical is readable by prior versions of pandas (< 0.15.2), but will retrieve the data as an integer based column (e.g. the codes). 但是,可以检索categories 可以,但需要用户使用显式元路径手动选择它们。

数据存储如下:

In [432]: cstore
Out[432]: 
<class 'pandas.io.pytables.HDFStore'>
File path: cats.h5
/dfcat                        frame_table  (typ->appendable,nrows->8,ncols->2,indexers->[index],dc->[A])     
/dfcat/meta/A/meta            series_table (typ->appendable,nrows->4,ncols->1,indexers->[index],dc->[values])

# to get the categories
In [433]: cstore.select('dfcat/meta/A/meta')
Out[433]: 
0    a
1    b
2    c
3    d
dtype: object

String Columns

min_itemsize

HDFStore的底层实现对字符串列使用固定列宽(itemsize)。字符串列itemsize计算为传递到第一个附加中的HDFStore的数据长度的最大值(对于该列)。Subsequent appends, may introduce a string for a column larger than the column can hold, an Exception will be raised (otherwise you could have a silent truncation of these columns, leading to loss of information). 在将来,我们可以放松这一点,并允许发生用户指定的截断。

将第一个表创建的min_itemsize传递给先验指定特定字符串列的最小长度。min_itemsize可以是整数,也可以是将列名称映射为整数的dict。您可以传递values作为键,以允许所有可索引项data_columns具有此min_itemsize。

从0.11.0开始,传递min_itemsize dict将使所有传递的列自动创建为data_columns

注意

如果您未传递任何data_columns,则min_itemsize将是传递的任何字符串的长度的最大值

In [434]: dfs = pd.DataFrame(dict(A = 'foo', B = 'bar'),index=list(range(5)))

In [435]: dfs
Out[435]: 
     A    B
0  foo  bar
1  foo  bar
2  foo  bar
3  foo  bar
4  foo  bar

# A and B have a size of 30
In [436]: store.append('dfs', dfs, min_itemsize = 30)

In [437]: store.get_storer('dfs').table
Out[437]: 
/dfs/table (Table(5,)) ''
  description := {
  "index": Int64Col(shape=(), dflt=0, pos=0),
  "values_block_0": StringCol(itemsize=30, shape=(2,), dflt='', pos=1)}
  byteorder := 'little'
  chunkshape := (963,)
  autoindex := True
  colindexes := {
    "index": Index(6, medium, shuffle, zlib(1)).is_csi=False}

# A is created as a data_column with a size of 30
# B is size is calculated
In [438]: store.append('dfs2', dfs, min_itemsize = { 'A' : 30 })

In [439]: store.get_storer('dfs2').table
Out[439]: 
/dfs2/table (Table(5,)) ''
  description := {
  "index": Int64Col(shape=(), dflt=0, pos=0),
  "values_block_0": StringCol(itemsize=3, shape=(1,), dflt='', pos=1),
  "A": StringCol(itemsize=30, shape=(), dflt='', pos=2)}
  byteorder := 'little'
  chunkshape := (1598,)
  autoindex := True
  colindexes := {
    "A": Index(6, medium, shuffle, zlib(1)).is_csi=False,
    "index": Index(6, medium, shuffle, zlib(1)).is_csi=False}

nan_rep

字符串列将使用nan_rep字符串表示形式将np.nan(缺少的值)序列化。默认为字符串值nan您可能无意中将实际的nan值转换为缺失值。

In [440]: dfss = pd.DataFrame(dict(A = ['foo','bar','nan']))

In [441]: dfss
Out[441]: 
     A
0  foo
1  bar
2  nan

In [442]: store.append('dfss', dfss)

In [443]: store.select('dfss')
Out[443]: 
     A
0  foo
1  bar
2  NaN

# here you need to specify a different nan rep
In [444]: store.append('dfss2', dfss, nan_rep='_nan_')

In [445]: store.select('dfss2')
Out[445]: 
     A
0  foo
1  bar
2  nan

External Compatibility

HDFStore以特定格式写入table格式对象,适合生成对pandas对象的无丢失往返。为了外部兼容性,HDFStore可以读取原生PyTables格式表。

可以使用rhdf5库(包网站)将可以轻松导入RHDFStore )。创建一个表格式存储像这样:

In [446]: np.random.seed(1)

In [447]: df_for_r = pd.DataFrame({"first": np.random.rand(100),
   .....:                          "second": np.random.rand(100),
   .....:                          "class": np.random.randint(0, 2, (100,))},
   .....:                          index=range(100))
   .....: 

In [448]: df_for_r.head()
Out[448]: 
   class     first    second
0      0  0.417022  0.326645
1      0  0.720324  0.527058
2      1  0.000114  0.885942
3      1  0.302333  0.357270
4      1  0.146756  0.908535

In [449]: store_export = pd.HDFStore('export.h5')

In [450]: store_export.append('df_for_r', df_for_r, data_columns=df_dc.columns)

In [451]: store_export
Out[451]: 
<class 'pandas.io.pytables.HDFStore'>
File path: export.h5
/df_for_r            frame_table  (typ->appendable,nrows->100,ncols->3,indexers->[index])

在R中,这个文件可以使用rhdf5库读入data.frame对象。以下示例函数从值读取相应的列名称和数据值,并将它们组合到data.frame中:

# Load values and column names for all datasets from corresponding nodes and
# insert them into one data.frame object.

library(rhdf5)

loadhdf5data <- function(h5File) {

listing <- h5ls(h5File)
# Find all data nodes, values are stored in *_values and corresponding column
# titles in *_items
data_nodes <- grep("_values", listing$name)
name_nodes <- grep("_items", listing$name)
data_paths = paste(listing$group[data_nodes], listing$name[data_nodes], sep = "/")
name_paths = paste(listing$group[name_nodes], listing$name[name_nodes], sep = "/")
columns = list()
for (idx in seq(data_paths)) {
  # NOTE: matrices returned by h5read have to be transposed to to obtain
  # required Fortran order!
  data <- data.frame(t(h5read(h5File, data_paths[idx])))
  names <- t(h5read(h5File, name_paths[idx]))
  entry <- data.frame(data)
  colnames(entry) <- names
  columns <- append(columns, entry)
}

data <- data.frame(columns)

return(data)
}

现在您可以将DataFrame导入R:

> data = loadhdf5data("transfer.hdf5")
> head(data)
         first    second class
1 0.4170220047 0.3266449     0
2 0.7203244934 0.5270581     0
3 0.0001143748 0.8859421     1
4 0.3023325726 0.3572698     1
5 0.1467558908 0.9085352     1
6 0.0923385948 0.6233601     1

注意

R函数列出整个HDF5文件的内容,并从所有匹配的节点组装data.frame对象,因此,如果您已存储多个DataFrame对象到一个单一的HDF5文件。

Backwards Compatibility

HDFStore的0.10.1可读取在先前版本的pandas中创建的表,但不支持使用之前(未记录)方法的查询术语。HDFStore将会发出警告。您必须读取整个文件,并使用新格式写出,使用方法copy以利用更新。组属性pandas_version包含版本信息。copy需要一些选项,请参阅docstring。

# a legacy store
In [452]: legacy_store = pd.HDFStore(legacy_file_path,'r')

In [453]: legacy_store
Out[453]: 
<class 'pandas.io.pytables.HDFStore'>
File path: /home/joris/scipy/pandas/doc/source/_static/legacy_0.10.h5
/a                    series       (shape->[30])                                                                        
/b                    frame        (shape->[30,4])                                                                      
/df1_mixed            frame_table [0.10.0] (typ->appendable,nrows->30,ncols->11,indexers->[index])                      
/foo/bar              wide         (shape->[3,30,4])                                                                    
/p1_mixed             wide_table  [0.10.0] (typ->appendable,nrows->120,ncols->9,indexers->[major_axis,minor_axis])      
/p4d_mixed            ndim_table  [0.10.0] (typ->appendable,nrows->360,ncols->9,indexers->[items,major_axis,minor_axis])

# copy (and return the new handle)
In [454]: new_store = legacy_store.copy('store_new.h5')

In [455]: new_store
Out[455]: 
<class 'pandas.io.pytables.HDFStore'>
File path: store_new.h5
/a                    series       (shape->[30])                                                                
/b                    frame        (shape->[30,4])                                                              
/df1_mixed            frame_table  (typ->appendable,nrows->30,ncols->11,indexers->[index])                      
/foo/bar              wide         (shape->[3,30,4])                                                            
/p1_mixed             wide_table   (typ->appendable,nrows->120,ncols->9,indexers->[major_axis,minor_axis])      
/p4d_mixed            wide_table   (typ->appendable,nrows->360,ncols->9,indexers->[items,major_axis,minor_axis])

In [456]: new_store.close()

Performance

Experimental

HDFStore支持Panel4D存储。

In [457]: p4d = pd.Panel4D({ 'l1' : wp })

In [458]: p4d
Out[458]: 
<class 'pandas.core.panelnd.Panel4D'>
Dimensions: 1 (labels) x 2 (items) x 5 (major_axis) x 4 (minor_axis)
Labels axis: l1 to l1
Items axis: Item1 to Item2
Major_axis axis: 2000-01-01 00:00:00 to 2000-01-05 00:00:00
Minor_axis axis: A to D

In [459]: store.append('p4d', p4d)

In [460]: store
Out[460]: 
<class 'pandas.io.pytables.HDFStore'>
File path: store.h5
/df                     frame_table  (typ->appendable,nrows->8,ncols->3,indexers->[index])                         
/df1_mt                 frame_table  (typ->appendable,nrows->8,ncols->2,indexers->[index],dc->[A,B])               
/df2_mt                 frame_table  (typ->appendable,nrows->8,ncols->5,indexers->[index])                         
/df_coord               frame_table  (typ->appendable,nrows->1000,ncols->2,indexers->[index])                      
/df_dc                  frame_table  (typ->appendable,nrows->8,ncols->5,indexers->[index],dc->[B,C,string,string2])
/df_mask                frame_table  (typ->appendable,nrows->1000,ncols->2,indexers->[index])                      
/df_mi                  frame_table  (typ->appendable_multi,nrows->10,ncols->5,indexers->[index],dc->[bar,foo])    
/df_mixed               frame_table  (typ->appendable,nrows->8,ncols->7,indexers->[index])                         
/dfeq                   frame_table  (typ->appendable,nrows->10,ncols->1,indexers->[index],dc->[number])           
/dfq                    frame_table  (typ->appendable,nrows->10,ncols->4,indexers->[index],dc->[A,B,C,D])          
/dfs                    frame_table  (typ->appendable,nrows->5,ncols->2,indexers->[index])                         
/dfs2                   frame_table  (typ->appendable,nrows->5,ncols->2,indexers->[index],dc->[A])                 
/dfss                   frame_table  (typ->appendable,nrows->3,ncols->1,indexers->[index])                         
/dfss2                  frame_table  (typ->appendable,nrows->3,ncols->1,indexers->[index])                         
/dftd                   frame_table  (typ->appendable,nrows->10,ncols->3,indexers->[index],dc->[A,B,C])            
/foo/bar/bah            frame        (shape->[8,3])                                                                
/p4d                    wide_table   (typ->appendable,nrows->40,ncols->1,indexers->[items,major_axis,minor_axis])  
/wp                     wide_table   (typ->appendable,nrows->8,ncols->2,indexers->[major_axis,minor_axis])         

默认情况下,这些索引为三个轴项, major_axis, minor_axisAppendableTable上,可以使用第一个追加设置不同的索引方案,具体取决于您要如何存储数据。axes关键字与尺寸列表(当前必须比对象的总尺寸小1)相关联。这在创建表之后不能更改。

In [461]: store.append('p4d2', p4d, axes=['labels', 'major_axis', 'minor_axis'])

In [462]: store
Out[462]: 
<class 'pandas.io.pytables.HDFStore'>
File path: store.h5
/df                     frame_table  (typ->appendable,nrows->8,ncols->3,indexers->[index])                         
/df1_mt                 frame_table  (typ->appendable,nrows->8,ncols->2,indexers->[index],dc->[A,B])               
/df2_mt                 frame_table  (typ->appendable,nrows->8,ncols->5,indexers->[index])                         
/df_coord               frame_table  (typ->appendable,nrows->1000,ncols->2,indexers->[index])                      
/df_dc                  frame_table  (typ->appendable,nrows->8,ncols->5,indexers->[index],dc->[B,C,string,string2])
/df_mask                frame_table  (typ->appendable,nrows->1000,ncols->2,indexers->[index])                      
/df_mi                  frame_table  (typ->appendable_multi,nrows->10,ncols->5,indexers->[index],dc->[bar,foo])    
/df_mixed               frame_table  (typ->appendable,nrows->8,ncols->7,indexers->[index])                         
/dfeq                   frame_table  (typ->appendable,nrows->10,ncols->1,indexers->[index],dc->[number])           
/dfq                    frame_table  (typ->appendable,nrows->10,ncols->4,indexers->[index],dc->[A,B,C,D])          
/dfs                    frame_table  (typ->appendable,nrows->5,ncols->2,indexers->[index])                         
/dfs2                   frame_table  (typ->appendable,nrows->5,ncols->2,indexers->[index],dc->[A])                 
/dfss                   frame_table  (typ->appendable,nrows->3,ncols->1,indexers->[index])                         
/dfss2                  frame_table  (typ->appendable,nrows->3,ncols->1,indexers->[index])                         
/dftd                   frame_table  (typ->appendable,nrows->10,ncols->3,indexers->[index],dc->[A,B,C])            
/foo/bar/bah            frame        (shape->[8,3])                                                                
/p4d                    wide_table   (typ->appendable,nrows->40,ncols->1,indexers->[items,major_axis,minor_axis])  
/p4d2                   wide_table   (typ->appendable,nrows->20,ncols->2,indexers->[labels,major_axis,minor_axis]) 
/wp                     wide_table   (typ->appendable,nrows->8,ncols->2,indexers->[major_axis,minor_axis])         

In [463]: store.select('p4d2', [ pd.Term('labels=l1'), pd.Term('items=Item1'), pd.Term('minor_axis=A_big_strings') ])
Out[463]: 
<class 'pandas.core.panelnd.Panel4D'>
Dimensions: 0 (labels) x 1 (items) x 0 (major_axis) x 0 (minor_axis)
Labels axis: None
Items axis: Item1 to Item1
Major_axis axis: None
Minor_axis axis: None

SQL Queries

pandas.io.sql模块提供了一组查询包装器,以便于数据检索和减少对特定于数据库的API的依赖。数据库抽象由SQLAlchemy(如果已安装)提供。此外,您将需要一个用于数据库的驱动程序库。这种驱动程序的示例是PostgreSQL的psycopg2或MySQL的pymysql对于SQLite,默认情况下包含在Python的标准库中。您可以在SQLAlchemy docs中找到每种SQL方言的支持的驱动程序的概述。

版本0.14.0中的新功能。

如果未安装SQLAlchemy,则仅为sqlite提供回退(对于mysql,为向后兼容性,但不推荐使用,将在以后的版本中删除)。此模式需要一个参考Python DB-API的Python数据库适配器。

有关一些高级策略,另见一些cookbook examples

主要功能有:

read_sql_table(table_name,con [,schema,...]) 将SQL数据库表读入DataFrame。
read_sql_query(sql,con [,index_col,...]) 将SQL查询读入DataFrame。
read_sql(sql,con [,index_col,...]) 将SQL查询或数据库表读入DataFrame。
DataFrame.to_sql(name,con [,flavor,...]) 将存储在DataFrame中的记录写入SQL数据库。

注意

函数read_sql()是围绕read_sql_table()read_sql_query()(以及为了向后兼容)的方便包装,取决于提供的输入(数据库表名或sql查询)。如果表名称具有特殊字符,则不需要引用。

在以下示例中,我们使用SQlite SQL数据库引擎。您可以使用临时SQLite数据库,其中数据存储在“内存”中。

要使用SQLAlchemy连接,可以使用create_engine()函数从数据库URI创建引擎对象。每个要连接的数据库只需创建引擎一次。有关create_engine()和URI格式的更多信息,请参阅下面的示例和SQLAlchemy 文档

In [464]: from sqlalchemy import create_engine

# Create your engine.
In [465]: engine = create_engine('sqlite:///:memory:')

with engine.connect() as conn, conn.begin():
    data = pd.read_sql_table('data', conn)

Writing DataFrames

假设以下数据在DataFrame data中,我们可以使用to_sql()将其插入数据库。

ID 日期 Col_1 Col_2 Col_3
26 2012-10-18 X 25.7 真正
42 2012-10-19 Y -12.4
63 2012-10-20 Z 5.73 真正
In [466]: data.to_sql('data', engine)

对于某些数据库,由于超过了数据包大小限制,写入大型DataFrames可能会导致错误。这可以通过在调用to_sql时设置chunksize参数来避免。例如,以下将data以批处理形式批量写入数据库:每次1000行:

In [467]: data.to_sql('data_chunked', engine, chunksize=1000)

SQL data types

to_sql()将尝试根据数据的dtype将数据映射到适当的SQL数据类型。当您有dtype object的列时,pandas将尝试推断数据类型。

您可以通过使用dtype参数指定任何列的所需SQL类型来覆盖默认类型。此参数需要一个字典将列名称映射到SQLAlchemy类型(或sqlite3回退模式的字符串)。例如,指定对字符串列使用sqlalchemy String类型而不是默认的Text类型:

In [468]: from sqlalchemy.types import String

In [469]: data.to_sql('data_dtype', engine, dtype={'Col_1': String})

注意

由于timedelta在不同数据库风格中的支持有限,因此类型为timedelta64的列将作为整数值写入数据库中,并将生成警告。

注意

category dtype的列将转换为密集表示,如您在np.asarray(categorical)(例如,对于字符串类别,这将提供一个字符串数组)。因此,读取数据库表时,不会生成分类。

Reading Tables

read_sql_table()将读取给定表名称和可选的要读取的列子集的数据库表。

注意

要使用read_sql_table(),您必须安装SQLAlchemy可选依赖项。

In [470]: pd.read_sql_table('data', engine)
Out[470]: 
   index  id       Date Col_1  Col_2  Col_3
0      0  26 2010-10-18     X  27.50   True
1      1  42 2010-10-19     Y -12.50  False
2      2  63 2010-10-20     Z   5.73   True

您还可以将列的名称指定为DataFrame索引,并指定要读取的列的子集。

In [471]: pd.read_sql_table('data', engine, index_col='id')
Out[471]: 
    index       Date Col_1  Col_2  Col_3
id                                      
26      0 2010-10-18     X  27.50   True
42      1 2010-10-19     Y -12.50  False
63      2 2010-10-20     Z   5.73   True

In [472]: pd.read_sql_table('data', engine, columns=['Col_1', 'Col_2'])
Out[472]: 
  Col_1  Col_2
0     X  27.50
1     Y -12.50
2     Z   5.73

您可以明确强制将列解析为日期:

In [473]: pd.read_sql_table('data', engine, parse_dates=['Date'])
Out[473]: 
   index  id       Date Col_1  Col_2  Col_3
0      0  26 2010-10-18     X  27.50   True
1      1  42 2010-10-19     Y -12.50  False
2      2  63 2010-10-20     Z   5.73   True

如果需要,您可以显式指定格式字符串或要传递给pandas.to_datetime()的参数的dict:

pd.read_sql_table('data', engine, parse_dates={'Date': '%Y-%m-%d'})
pd.read_sql_table('data', engine, parse_dates={'Date': {'format': '%Y-%m-%d %H:%M:%S'}})

您可以使用has_table()检查表是否存在

Schema support

版本0.15.0中的新功能。

通过read_sql_table()to_sql()函数中的schema关键字支持读取和写入不同模式。注意,这取决于数据库风格(sqlite没有模式)。例如:

df.to_sql('table', engine, schema='other_schema')
pd.read_sql_table('table', engine, schema='other_schema')

Querying

您可以在read_sql_query()函数中使用原始SQL进行查询。在这种情况下,必须使用适合于数据库的SQL变量。当使用SQLAlchemy时,还可以传递SQLAlchemy Expression语言构造,这是数据库不可知的。

In [474]: pd.read_sql_query('SELECT * FROM data', engine)
Out[474]: 
   index  id                        Date Col_1  Col_2  Col_3
0      0  26  2010-10-18 00:00:00.000000     X  27.50      1
1      1  42  2010-10-19 00:00:00.000000     Y -12.50      0
2      2  63  2010-10-20 00:00:00.000000     Z   5.73      1

当然,你可以指定一个更“复杂”的查询。

In [475]: pd.read_sql_query("SELECT id, Col_1, Col_2 FROM data WHERE id = 42;", engine)
Out[475]: 
   id Col_1  Col_2
0  42     Y  -12.5

read_sql_query()函数支持chunksize参数。指定这将返回一个迭代器通过查询结果的块:

In [476]: df = pd.DataFrame(np.random.randn(20, 3), columns=list('abc'))

In [477]: df.to_sql('data_chunks', engine, index=False)
In [478]: for chunk in pd.read_sql_query("SELECT * FROM data_chunks", engine, chunksize=5):
   .....:     print(chunk)
   .....: 
          a         b         c
0  0.280665 -0.073113  1.160339
1  0.369493  1.904659  1.111057
2  0.659050 -1.627438  0.602319
3  0.420282  0.810952  1.044442
4 -0.400878  0.824006 -0.562305
          a         b         c
0  1.954878 -1.331952 -1.760689
1 -1.650721 -0.890556 -1.119115
2  1.956079 -0.326499 -1.342676
3  1.114383 -0.586524 -1.236853
4  0.875839  0.623362 -0.434957
          a         b         c
0  1.407540  0.129102  1.616950
1  0.502741  1.558806  0.109403
2 -1.219744  2.449369 -0.545774
3 -0.198838 -0.700399 -0.203394
4  0.242669  0.201830  0.661020
          a         b         c
0  1.792158 -0.120465 -1.233121
1 -1.182318 -0.665755 -1.674196
2  0.825030 -0.498214 -0.310985
3 -0.001891 -1.396620 -0.861316
4  0.674712  0.618539 -0.443172

您还可以运行纯查询,而不使用execute()创建数据帧。这对于不返回值的查询很有用,例如INSERT。这在功能上等同于在SQLAlchemy引擎或db连接对象上调用execute同样,您必须使用适合您的数据库的SQL语法变体。

from pandas.io import sql
sql.execute('SELECT * FROM table_name', engine)
sql.execute('INSERT INTO table_name VALUES(?, ?, ?)', engine, params=[('id', 1, 12.2, True)])

Engine connection examples

要使用SQLAlchemy连接,可以使用create_engine()函数从数据库URI创建引擎对象。每个要连接的数据库只需创建引擎一次。

from sqlalchemy import create_engine

engine = create_engine('postgresql://scott:tiger@localhost:5432/mydatabase')

engine = create_engine('mysql+mysqldb://scott:tiger@localhost/foo')

engine = create_engine('oracle://scott:tiger@127.0.0.1:1521/sidname')

engine = create_engine('mssql+pyodbc://mydsn')

# sqlite://<nohostname>/<path>
# where <path> is relative:
engine = create_engine('sqlite:///foo.db')

# or absolute, starting with a slash:
engine = create_engine('sqlite:////absolute/path/to/foo.db')

有关更多信息,请参见SQLAlchemy 文档示例

Advanced SQLAlchemy queries

您可以使用SQLAlchemy结构来描述您的查询。

使用sqlalchemy.text()以后端中性方式指定查询参数

In [479]: import sqlalchemy as sa

In [480]: pd.read_sql(sa.text('SELECT * FROM data where Col_1=:col1'), engine, params={'col1': 'X'})
Out[480]: 
   index  id                        Date Col_1  Col_2  Col_3
0      0  26  2010-10-18 00:00:00.000000     X   27.5      1

如果您有数据库的SQLAlchemy描述,可以使用SQLAlchemy表达式表达条件

In [481]: metadata = sa.MetaData()

In [482]: data_table = sa.Table('data', metadata,
   .....:     sa.Column('index', sa.Integer),
   .....:     sa.Column('Date', sa.DateTime),
   .....:     sa.Column('Col_1', sa.String),
   .....:     sa.Column('Col_2', sa.Float),
   .....:     sa.Column('Col_3', sa.Boolean),
   .....: )
   .....: 

In [483]: pd.read_sql(sa.select([data_table]).where(data_table.c.Col_3 == True), engine)
Out[483]: 
   index       Date Col_1  Col_2 Col_3
0      0 2010-10-18     X  27.50  True
1      2 2010-10-20     Z   5.73  True

您可以使用sqlalchemy.bindparam()将SQLAlchemy表达式与传递给read_sql()

In [484]: import datetime as dt

In [485]: expr = sa.select([data_table]).where(data_table.c.Date > sa.bindparam('date'))

In [486]: pd.read_sql(expr, engine, params={'date': dt.datetime(2010, 10, 18)})
Out[486]: 
   index       Date Col_1  Col_2  Col_3
0      1 2010-10-19     Y -12.50  False
1      2 2010-10-20     Z   5.73   True

Sqlite fallback

不使用SQLAlchemy支持sqlite的使用。此模式需要一个尊重Python DB-API的Python数据库适配器。

您可以创建如下所示的连接:

import sqlite3
con = sqlite3.connect(':memory:')

然后发出以下查询:

data.to_sql('data', cnx)
pd.read_sql_query("SELECT * FROM data", con)

Google BigQuery (Experimental)

版本0.13.0中的新功能。

pandas.io.gbq模块为Google的BigQuery分析网络服务提供了一个包装器,以简化使用类似SQL的查询从BigQuery表中检索结果。结果集将解析为具有从源表派生的形状和数据类型的pandas DataFrame。此外,DataFrames可以插入新的BigQuery表或附加到现有表。

您将需要安装一些额外的依赖:

警告

要使用此模块,您需要一个有效的BigQuery帐户。有关服务本身的详细信息,请参阅BigQuery文档

主要功能有:

read_gbq(query [,project_id,index_col,...]) 从Google BigQuery载入数据。
to_gbq(dataframe,destination_table,project_id) 将DataFrame写入Google BigQuery表格。

Authentication

版本0.18.0中的新功能。

Google BigQuery服务的验证是通过OAuth 2.0进行。可以使用用户帐户凭据或服务帐户凭据进行身份验证。

使用用户帐户凭据进行身份验证与浏览器窗口中的提示一样简单,会自动为您打开。您将使用产品名称pandas GBQ向指定的BigQuery帐户验证身份。它只能在本地主机上。Pandas当前不支持使用用户帐户凭据的远程身份验证。有关身份验证机制的其他信息,请参见此处

可以通过'private_key'参数进行具有服务帐户凭据的身份验证。当在远程服务器上工作时,此方法特别有用(例如。远程主机上的jupyter iPython笔记本)。有关服务帐户的其他信息,请访问此处

您需要安装附加的依赖项:oauth2client

还可以通过应用 默认 凭据这仅在未提供参数private_key时有效。此方法还要求可以从代码运行的环境中获取凭据。否则,将使用OAuth2客户端身份验证。有关应用程序默认凭据的其他信息。

版本0.19.0中的新功能。

注意

'private_key'参数可以设置为JSON格式的服务帐户密钥的文件路径,或JSON格式的服务帐户密钥的密钥内容。

注意

您可以点击此处从Google开发者控制台获取私钥。使用JSON键类型。

Querying

假设您要使用read_gbq()函数将现有BigQuery表中的所有数据加载到DataFrame:test_dataset.test_table

# Insert your BigQuery Project ID Here
# Can be found in the Google web console
projectid = "xxxxxxxx"

data_frame = pd.read_gbq('SELECT * FROM test_dataset.test_table', projectid)

您可以定义BigQuery中的哪个列用作目标DataFrame中的索引以及首选列顺序,如下所示:

data_frame = pd.read_gbq('SELECT * FROM test_dataset.test_table',
                          index_col='index_column_name',
                          col_order=['col1', 'col2', 'col3'], projectid)

注意

您可以在Google开发人员控制台中找到您的专案ID。

注意

您可以通过默认为Trueverbose标志切换详细输出。

注意

dialect参数可用于指示是否使用BigQuery的'legacy' SQL或BigQuery的'standard' SQL(测试版)。默认值为'legacy'有关BigQuery标准SQL的详情,请参阅BigQuery SQL参考

Writing DataFrames

假设我们要使用to_gbq()将DataFrame df写入BigQuery表格中。

In [487]: df = pd.DataFrame({'my_string': list('abc'),
   .....:                    'my_int64': list(range(1, 4)),
   .....:                    'my_float64': np.arange(4.0, 7.0),
   .....:                    'my_bool1': [True, False, True],
   .....:                    'my_bool2': [False, True, False],
   .....:                    'my_dates': pd.date_range('now', periods=3)})
   .....: 

In [488]: df
Out[488]: 
  my_bool1 my_bool2                   my_dates  my_float64  my_int64 my_string
0     True    False 2016-12-24 18:33:33.411047         4.0         1         a
1    False     True 2016-12-25 18:33:33.411047         5.0         2         b
2     True    False 2016-12-26 18:33:33.411047         6.0         3         c

In [489]: df.dtypes
Out[489]: 
my_bool1                bool
my_bool2                bool
my_dates      datetime64[ns]
my_float64           float64
my_int64               int64
my_string             object
dtype: object
df.to_gbq('my_dataset.my_table', projectid)

注意

如果目标表和目标数据集不存在,将自动创建它们。

if_exists参数可用于指示是否'fail''replace''append' if目标表已存在。默认值为'fail'

例如,假设if_exists设置为'fail'如果目标表已存在,以下代码段将产生TableCreationError

df.to_gbq('my_dataset.my_table', projectid, if_exists='fail')

注意

如果if_exists参数设置为'append',则将使用定义的表模式和列类型将目标数据帧写入表。数据帧必须与结构和数据类型中的目标表相匹配。如果if_exists参数设置为'replace',并且现有表具有不同的模式,则将强制延迟2分钟以确保新模式已传播在Google环境中。请参阅Google BigQuery问题191

写入大型DataFrames可能会由于超出大小限制而导致错误。这可以通过在调用to_gbq()时设置chunksize参数来避免。例如,以下将df以批处理形式批量写入BigQuery表中:每次10000行:

df.to_gbq('my_dataset.my_table', projectid, chunksize=10000)

您还可以通过默认为Trueverbose标志查看您的帖子的进度。例如:

In [8]: df.to_gbq('my_dataset.my_table', projectid, chunksize=10000, verbose=True)

        Streaming Insert is 10% Complete
        Streaming Insert is 20% Complete
        Streaming Insert is 30% Complete
        Streaming Insert is 40% Complete
        Streaming Insert is 50% Complete
        Streaming Insert is 60% Complete
        Streaming Insert is 70% Complete
        Streaming Insert is 80% Complete
        Streaming Insert is 90% Complete
        Streaming Insert is 100% Complete

注意

如果在将数据流式传输到BigQuery时发生错误,请参阅排查BigQuery错误

注意

BigQuery SQL查询语言有一些异常,请参阅BigQuery查询参考文档

注意

虽然BigQuery使用类似SQL的语法,但它在功能,API限制(查询或上传的大小和数量)以及Google对服务使用收费方面与传统数据库有一些重要差异。由于服务似乎在变化和发展,因此您应经常参阅Google BigQuery文档BiqQuery最适合快速分析大量数据,但不能直接替换事务数据库。

Creating BigQuery Tables

警告

从0.17开始,函数generate_bq_schema()已被弃用,并将在未来版本中删除。

从0.15.2开始,gbq模块具有函数generate_bq_schema(),它将产生指定的pandas DataFrame的字典表示模式。

In [10]: gbq.generate_bq_schema(df, default_type='STRING')

Out[10]: {'fields': [{'name': 'my_bool1', 'type': 'BOOLEAN'},
         {'name': 'my_bool2', 'type': 'BOOLEAN'},
         {'name': 'my_dates', 'type': 'TIMESTAMP'},
         {'name': 'my_float64', 'type': 'FLOAT'},
         {'name': 'my_int64', 'type': 'INTEGER'},
         {'name': 'my_string', 'type': 'STRING'}]}

注意

如果您删除并重新创建具有相同名称但表格架构不同的BigQuery表,则必须等待2分钟才能将数据流式传输到表中。作为解决方法,请考虑使用不同的名称创建新表。请参阅Google BigQuery问题191

Stata Format

版本0.12.0中的新功能。

Writing to Stata format

方法to_stata()会将DataFrame写入.dta文件。此文件的格式版本始终为115(Stata 12)。

In [490]: df = pd.DataFrame(randn(10, 2), columns=list('AB'))

In [491]: df.to_stata('stata.dta')

Stata data files have limited data type support; only strings with 244 or fewer characters, int8, int16, int32, float32 and float64 can be stored in .dta files. 此外,Stata保留某些值以表示缺失的数据。导出特定数据类型的Stata中允许范围之外的非缺失值将会将该变量重新键入下一个较大的大小。例如,在Stata中,int8的值被限制在-127和100之间,因此值大于100的变量将触发到int16的转换。浮点数据类型中的nan值被存储为基本丢失数据类型(.Stata)。

注意

不能导出整数数据类型的缺失数据值。

The Stata writer gracefully handles other data types including int64, bool, uint8, uint16, uint32 by casting to the smallest supported type that can represent the data. For example, data with a type of uint8 will be cast to int8 if all values are less than 100 (the upper bound for non-missing int8 data in Stata), or, if values are outside of this range, the variable is cast to int16.

警告

如果int64值大于2 ** 53,则从int64float64的转换可能会导致精度损失。

警告

StataWriterto_stata()仅支持包含最多244个字符的固定宽度字符串,这是版本115 dta文件格式强加的限制。尝试使用长度超过244个字符的字符串写入Stata dta文件会引发ValueError

Reading from Stata format

顶层函数read_stata将读取一个dta文件,并返回一个DataFrame或一个StataReader,用于以增量方式读取文件。

In [492]: pd.read_stata('stata.dta')
Out[492]: 
   index         A         B
0      0  1.810535 -1.305727
1      1 -0.344987 -0.230840
2      2 -2.793085  1.937529
3      3  0.366332 -1.044589
4      4  2.051173  0.585662
5      5  0.429526 -0.606998
6      6  0.106223 -1.525680
7      7  0.795026 -0.374438
8      8  0.134048  1.202055
9      9  0.284748  0.262467

版本0.16.0中的新功能。

指定chunksize会生成一个StataReader实例,用于一次从文件中读取chunksize行。StataReader对象可以用作迭代器。

In [493]: reader = pd.read_stata('stata.dta', chunksize=3)

In [494]: for df in reader:
   .....:     print(df.shape)
   .....: 
(3, 3)
(3, 3)
(3, 3)
(1, 3)

对于更细粒度的控制,使用iterator=True并在每次调用read()时指定chunksize

In [495]: reader = pd.read_stata('stata.dta', iterator=True)

In [496]: chunk1 = reader.read(5)

In [497]: chunk2 = reader.read(5)

目前,index作为列检索。

参数convert_categoricals指示是否应读取值标签,并使用它们从中创建Categorical变量。值标签也可以通过函数value_labels检索,这需要在使用之前调用read()

参数convert_missing指示是否应保留Stata中的缺失值表示。如果False(默认值),则缺失值表示为np.nan如果True,则使用StataMissingValue对象表示缺失值,包含缺少值的列将具有object数据类型。

注意

read_stata()StataReader支持.dta格式113-115(Stata 10-12),117(Stata 13)和118(Stata 14)。

注意

设置preserve_dtypes=False将向上转换为标准的pandas数据类型:对于所有整数类型为int64,对于浮点数据为float64默认情况下,Stata数据类型在导入时保留。

Categorical Data

版本0.15.2中的新功能。

Categorical数据可以作为值标记数据导出到Stata数据文件。导出的数据由作为整数数据值的底层类别代码和作为值标签的类别组成。Stata没有显式等效于Categorical,并且有关变量是否有序的信息在导出时会丢失。

警告

Stata仅支持字符串值标签,因此导出数据时,类别上调用str导出具有非字符串类别的Categorical变量​​会产生警告,如果类别的str表示不唯一,则可能导致信息丢失。

使用关键字参数convert_categoricals(默认情况下为True),可以类似地将Stata数据文件中的标签数据导入为Categorical关键字参数order_categoricals(默认情况下为True)决定导入的Categorical变量是否有序。

注意

导入分类数据时,Stata数据文件中的变量值不会保留,因为Categorical变量始终使用整数数据类型-1n-1其中n是类别的数量。如果需要Stata数据文件中的原始值,可以通过设置convert_categoricals=False导入这些值,这将导入原始数据(但不导入变量标签)。The original values can be matched to the imported categorical data since there is a simple mapping between the original Stata data values and the category codes of imported Categorical variables: missing values are assigned code -1, and the smallest original value is assigned 0, the second smallest is assigned 1 and so on until the largest original value is assigned the code n-1.

注意

Stata支持部分标记的系列。这些系列具有一些但不是所有数据值的值标签。Importing a partially labeled series will produce a Categorical with string categories for the values that are labeled and numeric categories for values with no label.

SAS Formats

版本0.17.0中的新功能。

顶层函数read_sas()可读取SAS xport(.XPT)和SAS7BDAT(.sas7bdat)格式文件在v0.18.0中添加。

SAS文件只包含两种值类型:ASCII文本和浮点值(通常为8字节,但有时被截断)。对于xport文件,没有自动类型转换为整数,日期或分类。对于SAS7BDAT文件,格式代码可以允许日期变量自动转换为日期。默认情况下,读取整个文件并将其作为DataFrame返回。

指定chunksize或使用iterator=True获取读取器对象(XportReaderSAS7BDATReader), 。阅读器对象还具有包含有关文件及其变量的附加信息的属性。

读取SAS7BDAT文件:

df = pd.read_sas('sas_data.sas7bdat')

获取一个迭代器,并一次读取一个XPORT文件10万行:

rdr = pd.read_sas('sas_xport.xpt', chunk=100000)
for chunk in rdr:
    do_something(chunk)

xport文件格式的规范可从SAS网站获取。

没有官方文档可用于SAS7BDAT格式。

Other file formats

pandas本身只支持有一组有限的文件格式的IO,它们清楚地映射到它的表格数据模型。对于从pandas中读取和写入其他文件格式,我们推荐来自更广泛的社区的这些包。

netCDF

xarray提供了由pandas DataFrame启发的用于处理多维数据集的数据结构,重点是netCDF文件格式,并且易于转换到pandas。

Performance Considerations

这是使用pandas 0.13.1的各种IO方法的非正式比较。

In [1]: df = pd.DataFrame(randn(1000000,2),columns=list('AB'))

In [2]: df.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 1000000 entries, 0 to 999999
Data columns (total 2 columns):
A    1000000 non-null float64
B    1000000 non-null float64
dtypes: float64(2)
memory usage: 22.9 MB

写作

In [14]: %timeit test_sql_write(df)
1 loops, best of 3: 6.24 s per loop

In [15]: %timeit test_hdf_fixed_write(df)
1 loops, best of 3: 237 ms per loop

In [26]: %timeit test_hdf_fixed_write_compress(df)
1 loops, best of 3: 245 ms per loop

In [16]: %timeit test_hdf_table_write(df)
1 loops, best of 3: 901 ms per loop

In [27]: %timeit test_hdf_table_write_compress(df)
1 loops, best of 3: 952 ms per loop

In [17]: %timeit test_csv_write(df)
1 loops, best of 3: 3.44 s per loop

In [18]: %timeit test_sql_read()
1 loops, best of 3: 766 ms per loop

In [19]: %timeit test_hdf_fixed_read()
10 loops, best of 3: 19.1 ms per loop

In [28]: %timeit test_hdf_fixed_read_compress()
10 loops, best of 3: 36.3 ms per loop

In [20]: %timeit test_hdf_table_read()
10 loops, best of 3: 39 ms per loop

In [29]: %timeit test_hdf_table_read_compress()
10 loops, best of 3: 60.6 ms per loop

In [22]: %timeit test_csv_read()
1 loops, best of 3: 620 ms per loop

磁盘空间(以字节为单位)

25843712 Apr  8 14:11 test.sql
24007368 Apr  8 14:11 test_fixed.hdf
15580682 Apr  8 14:11 test_fixed_compress.hdf
24458444 Apr  8 14:11 test_table.hdf
16797283 Apr  8 14:11 test_table_compress.hdf
46152810 Apr  8 14:11 test.csv

这里是代码

import sqlite3
import os
from pandas.io import sql

df = pd.DataFrame(randn(1000000,2),columns=list('AB'))

def test_sql_write(df):
    if os.path.exists('test.sql'):
        os.remove('test.sql')
    sql_db = sqlite3.connect('test.sql')
    df.to_sql(name='test_table', con=sql_db)
    sql_db.close()

def test_sql_read():
    sql_db = sqlite3.connect('test.sql')
    pd.read_sql_query("select * from test_table", sql_db)
    sql_db.close()

def test_hdf_fixed_write(df):
    df.to_hdf('test_fixed.hdf','test',mode='w')

def test_hdf_fixed_read():
    pd.read_hdf('test_fixed.hdf','test')

def test_hdf_fixed_write_compress(df):
    df.to_hdf('test_fixed_compress.hdf','test',mode='w',complib='blosc')

def test_hdf_fixed_read_compress():
    pd.read_hdf('test_fixed_compress.hdf','test')

def test_hdf_table_write(df):
    df.to_hdf('test_table.hdf','test',mode='w',format='table')

def test_hdf_table_read():
    pd.read_hdf('test_table.hdf','test')

def test_hdf_table_write_compress(df):
    df.to_hdf('test_table_compress.hdf','test',mode='w',complib='blosc',format='table')

def test_hdf_table_read_compress():
    pd.read_hdf('test_table_compress.hdf','test')

def test_csv_write(df):
    df.to_csv('test.csv',mode='w')

def test_csv_read():
    pd.read_csv('test.csv',index_col=0)