赞
踩
前面我们介绍了 pandas
的基础语法操作,下面我们开始介绍 pandas
的数据读写操作。
pandas
的 IO
API
是一组顶层的 reader
函数,比如 pandas.read_csv()
,会返回一个 pandas
对象。
而相应的 writer
函数是对象方法,如 DataFrame.to_csv()
。
下面列出了所有的 reader
和 writer
函数
注意:后面会用到 StringIO
,请确保导入
# python3
from io import StringIO
# python2
from StringIO import StringIO
pandas
用于读取文本文件的主要函数是 read_csv()
,可以读取固定分隔符的文件,如 csv
、txt
、tsv
以及 xls
等
read_csv()
接受以下常用参数:
filepath_or_buffer
: 变量
URL
或任何带有 read()
函数的对象sep
: str
,默认 ,
,对于 read_table
是 \t
None
,则 C
引擎无法自动检测分隔符,而 Python
引擎可以通过内置的嗅探器工具自动检测分隔符。1
,且不是 '\s+'
,那么该字符串会被解析为正则表达式,且强制使用 Python
解析引擎。'\\r\\t'
,但是正则表达式容易忽略文本中的引用数据。delimiter
: str
, 默认为 None
sep
的替代参数,功能一致header
: int
或 list
, 默认为 'infer'
names
参数其行为类似于 header=0
,即从读取的第一行开始推断。names
,则行为与 header=None
相同。header
设置列表,表示多级列名。如 [0,1,3]
,未指定的行(这里是 2
)将会被跳过,如果 skip_blank_lines=True
,则会跳过空行和注释的行。因此 header=0
并不是代表文件的第一行names
: array-like
, 默认为 None
header=None
,且此列表中不允许有重复值。index_col
: int
, str
, sequence of int/str
, False
, 默认为 None
用作 DataFrame
的索引的列,可以字符串名称或列索引的形式给出。如果指定了列表,则使用 MultiIndex
注意:index_col=False
可用于强制 pandas
不要将第一列用作索引。例如,当您的文件是每行末尾都带有一个分隔符的错误文件时。
usecols
: 列表或函数, 默认为 None
只读取指定的列。如果是列表,则所有元素都必须是位置(即文件列中的整数索引)或字符串,这些字符串必须与 names
参数提供的或从文档标题行推断出的列名相对应。
列表中的顺序会被忽略,即 usecols=[0, 1]
等价于 [1, 0]
如果是可调用函数,将会根据列名计算,返回可调用函数计算为 True
的名称
In [1]: import pandas as pd In [2]: from io import StringIO In [3]: data = "col1,col2,col3\na,b,1\na,b,2\nc,d,3" In [4]: pd.read_csv(StringIO(data)) Out[4]: col1 col2 col3 0 a b 1 1 a b 2 2 c d 3 In [5]: pd.read_csv(StringIO(data), usecols=lambda x: x.upper() in ["COL1", "COL3"]) Out[5]: col1 col3 0 a 1 1 a 2 2 c 3
使用此参数可以大大加快解析时间并降低内存使用
squeeze
: boolean
, 默认为 False
Series
prefix
: str
, 默认为 None
'X'
表示 X0
, X1
…mangle_dupe_cols
: boolean
, 默认为 True
'X'
,'X.1'
…'X.N'
,而不是 'X'
… 。如果在列中有重复的名称,传递 False
将导致数据被覆盖dtype
: 类型名或类型字典(column -> type
), 默认为 None
{'a':np.float64,'b':np.int32}
engine
: {'c', 'python'}
C
引擎更快,而 Python
引擎目前功能更完整converters
: dict
, 默认为 None
true_values
: list
, 默认为 None
True
false_values
: list
, 默认为 None
False
skipinitialspace
: boolean
, 默认为 False
skiprows
: 整数或整数列表, 默认为 None
在文件开头要跳过的行号(索引为 0
)或要跳过的行数
如果可调用函数,则对索引应用函数,如果返回 True
,则应跳过该行,否则返回 False
In [6]: data = "col1,col2,col3\na,b,1\na,b,2\nc,d,3"
In [7]: pd.read_csv(StringIO(data))
Out[7]:
col1 col2 col3
0 a b 1
1 a b 2
2 c d 3
In [8]: pd.read_csv(StringIO(data), skiprows=lambda x: x % 2 != 0)
Out[8]:
col1 col2 col3
0 a b 2
skipfooter
: int
, 默认为 0
C
引擎)nrows
: int
, 默认为 None
memory_map
: boolean
, 默认为 False
filepath_or_buffer
参数指定了文件路径,则将文件对象直接映射到内存中,然后直接从那里访问数据。使用此选项可以提高性能,因为不再有任何 I/O
开销na_values
: scalar
, str
, list-like
, dict
, 默认为 None
NA
值的字符串keep_default_na
: boolean
, 默认为 True
解析数据时是否包含默认的 NaN
值。根据是否传入 na_values
,其行为如下
keep_default_na=True
, 且指定了 na_values
, na_values
将会与默认的 NaN
一起被解析
keep_default_na=True
, 且未指定 na_values
, 只解析默认的 NaN
keep_default_na=False
, 且指定了 na_values
, 只解析 na_values
指定的 NaN
keep_default_na=False
, 且未指定 na_values
, 字符串不会被解析为 NaN
注意:如果 na_filter=False
,那么 keep_default_na
和 na_values
参数将被忽略
na_filter
: boolean
, 默认为 True
na_values
的值)。在没有任何 NA
的数据中,设置 na_filter=False
可以提高读取大文件的性能skip_blank_lines
: boolean
, 默认为 True
True
,则跳过空行,而不是解释为 NaN
值parse_dates
: 布尔值、列表或嵌套列表、字典, 默认为 False
.
如果为 True
-> 尝试解析索引
如果为 [1, 2, 3]
-> 尝试将 1, 2, 3
列解析为分隔的日期
如果为 [[1, 3]]
-> 将 1, 3
列解析为单个日期列
如果为 {'foo': [1, 3]}
-> 将 1, 3
列作为日期并设置列名为 foo
infer_datetime_format
: 布尔值, 默认为 False
True
且设置了 parse_dates
,则尝试推断 datetime
格式以加快处理速度date_parser
: 函数, 默认为 None
dateutil.parser.parser
进行转换,pandas
将尝试以三种不同的方式调用 date_parser
parse_dates
定义的列)作为参数;parse_dates
定义的列中的字符串值连接到单个数组中,并将其传递;parse_dates
定义的列)作为参数,对每一行调用 date_parser
一次。dayfirst
: 布尔值, 默认为 False
DD/MM
格式的日期cache_dates
: 布尔值, 默认为 True
True
,则使用唯一的、经过转换的日期缓存来应用 datetime
转换。iterator
: boolean
, 默认为 False
TextFileReader
对象以进行迭代或使用 get_chunk()
来获取块compression
: {'infer', 'gzip', 'bz2', 'zip', 'xz', None, dict}
, 默认为 'infer'
用于对磁盘数据进行即时解压缩。如果为 "infer"
,则如果 filepath_or_buffer
是文件路径且以 ".gz"
,".bz2"
,".zip"
或 ".xz"
结尾,则分别使用 gzip
,bz2
,zip
或 xz
解压,否则不进行解压缩。
如果使用 "zip"
,则 ZIP
文件必须仅包含一个要读取的数据文件。设置为 None
表示不解压
也可以使用字典的方式,键为 method
的值从 {'zip', 'gzip', 'bz2'}
中选择。例如
compression={'method': 'gzip', 'compresslevel': 1, 'mtime': 1}
thousandsstr
, 默认为 None
decimal
: str
, 默认为 '.'
float_precision
: string
, 默认为 None
C
引擎应该使用哪个转换器来处理浮点值。普通转换器的选项为 None
,高精度转换器的选项为 high
,双向转换器的选项为 round_trip
。quotechar
: str
(长度为 1
)
comment
: str
, 默认为 None
comment='#'
,将会跳过 #
开头的行encoding
: str
, 默认为 None
error_bad_linesboolean
, 默认为 True
csv
文件)会引发异常,并且不会返回任何 DataFrame
。False
,则这些坏行将会被删除warn_bad_linesboolean
, 默认为 True
error_bad_lines=False
且 warn_bad_lines=True
,每个坏行都会输出一个警告您可以指示整个 DataFrame
或各列的数据类型
In [9]: import numpy as np In [10]: data = "a,b,c,d\n1,2,3,4\n5,6,7,8\n9,10,11" In [11]: print(data) a,b,c,d 1,2,3,4 5,6,7,8 9,10,11 In [12]: df = pd.read_csv(StringIO(data), dtype=object) In [13]: df Out[13]: a b c d 0 1 2 3 4 1 5 6 7 8 2 9 10 11 NaN In [14]: df["a"][0] Out[14]: '1' In [15]: df = pd.read_csv(StringIO(data), dtype={"b": object, "c": np.float64, "d": "Int64"}) In [16]: df.dtypes Out[16]: a int64 b object c float64 d Int64 dtype: object
你可以使用 read_csv()
的 converters
参数,统一某列的数据类型
In [17]: data = "col_1\n1\n2\n'A'\n4.22" In [18]: df = pd.read_csv(StringIO(data), converters={"col_1": str}) In [19]: df Out[19]: col_1 0 1 1 2 2 'A' 3 4.22 In [20]: df["col_1"].apply(type).value_counts() Out[20]: <class 'str'> 4 Name: col_1, dtype: int64
或者,您可以在读取数据后使用 to_numeric()
函数强制转换类型
In [21]: df2 = pd.read_csv(StringIO(data)) In [22]: df2["col_1"] = pd.to_numeric(df2["col_1"], errors="coerce") In [23]: df2 Out[23]: col_1 0 1.00 1 2.00 2 NaN 3 4.22 In [24]: df2["col_1"].apply(type).value_counts() Out[24]: <class 'float'> 4 Name: col_1, dtype: int64
它将所有有效的数值转换为浮点数,而将无效的解析为 NaN
最后,如何处理包含混合类型的列取决于你的具体需要。在上面的例子中,如果您只想要将异常的数据转换为 NaN
,那么 to_numeric()
可能是您的最佳选择。
然而,如果您想要强制转换所有数据,而无论类型如何,那么使用 read_csv()
的 converters
参数会更好
注意
在某些情况下,读取包含混合类型列的异常数据将导致数据集不一致。
如果您依赖
pandas
来推断列的类型,解析引擎将继续推断数据块的类型,而不是一次推断整个数据集。In [25]: col_1 = list(range(500000)) + ["a", "b"] + list(range(500000)) In [26]: df = pd.DataFrame({"col_1": col_1}) In [27]: df.to_csv("foo.csv") In [28]: mixed_df = pd.read_csv("foo.csv") In [29]: mixed_df["col_1"].apply(type).value_counts() Out[29]: <class 'int'> 737858 <class 'str'> 262144 Name: col_1, dtype: int64 In [30]: mixed_df["col_1"].dtype Out[30]: dtype('O')
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
这就导致
mixed_df
对于列的某些块包含int
类型,而对于其他块则包含str
,这是由于读取的数据是混合类型。
分类类型可以通过指定 dtype='category'
或 dtype=CategoricalDtype(categories, ordered)
直接解析
In [31]: data = "col1,col2,col3\na,b,1\na,b,2\nc,d,3" In [32]: pd.read_csv(StringIO(data)) Out[32]: col1 col2 col3 0 a b 1 1 a b 2 2 c d 3 In [33]: pd.read_csv(StringIO(data)).dtypes Out[33]: col1 object col2 object col3 int64 dtype: object In [34]: pd.read_csv(StringIO(data), dtype="category").dtypes Out[34]: col1 category col2 category col3 category dtype: object
也可以使用字典对指定列设置类型
In [35]: pd.read_csv(StringIO(data), dtype={"col1": "category"}).dtypes
Out[35]:
col1 category
col2 object
col3 int64
dtype: object
指定 dtype ='category'
将导致无序分类,其类别是数据中所有观察值的集合。
如果要更好地控制类别和顺序,请提前创建 CategoricalDtype
,然后将其传递给该列的 dtype
In [36]: from pandas.api.types import CategoricalDtype
In [37]: dtype = CategoricalDtype(["d", "c", "b", "a"], ordered=True)
In [38]: pd.read_csv(StringIO(data), dtype={"col1": dtype}).dtypes
Out[38]:
col1 category
col2 object
col3 int64
dtype: object
使用 dtype=CategoricalDtype
时,超出的数据类型将被视为缺失值
In [39]: dtype = CategoricalDtype(["a", "b", "d"]) # No 'c'
In [40]: pd.read_csv(StringIO(data), dtype={"col1": dtype}).col1
Out[40]:
0 a
1 a
2 NaN
Name: col1, dtype: category
Categories (3, object): ['a', 'b', 'd']
这与 Categorical.set_categories()
的行为相匹配
注意
当
dtype='category'
时,生成的类别将始终解析为字符串(object
类型)。如果类别是数字型,则可以使用
to_numeric()
函数或其他转换器进行转换,如to_datetime()
当dtype
是一个同构(所有数字、所有日期时间等)的CategoricalDtype
时,转换将自动完成In [41]: df = pd.read_csv(StringIO(data), dtype="category") In [42]: df.dtypes Out[42]: col1 category col2 category col3 category dtype: object In [43]: df["col3"] Out[43]: 0 1 1 2 2 3 Name: col3, dtype: category Categories (3, object): ['1', '2', '3'] In [44]: df["col3"].cat.categories = pd.to_numeric(df["col3"].cat.categories) In [45]: df["col3"] Out[45]: 0 1 1 2 2 3 Name: col3, dtype: category Categories (3, int64): [1, 2, 3]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
一个文件可能有也可能没有标题行,pandas
默认将第一行用作列名
In [46]: data = "a,b,c\n1,2,3\n4,5,6\n7,8,9"
In [47]: print(data)
a,b,c
1,2,3
4,5,6
7,8,9
In [48]: pd.read_csv(StringIO(data))
Out[48]:
a b c
0 1 2 3
1 4 5 6
2 7 8 9
通过将 names
参数与 header
一起使用
In [49]: print(data) a,b,c 1,2,3 4,5,6 7,8,9 In [50]: pd.read_csv(StringIO(data), names=["foo", "bar", "baz"], header=0) Out[50]: foo bar baz 0 1 2 3 1 4 5 6 2 7 8 9 In [51]: pd.read_csv(StringIO(data), names=["foo", "bar", "baz"], header=None) Out[51]: foo bar baz 0 a b c 1 1 2 3 2 4 5 6 3 7 8 9
如果标题不在第一行中,可以将行号传递给 header
,将会跳过前面的行
In [52]: data = "skip this skip it\na,b,c\n1,2,3\n4,5,6\n7,8,9"
In [53]: pd.read_csv(StringIO(data), header=1)
Out[53]:
a b c
0 1 2 3
1 4 5 6
2 7 8 9
如果文件或表头包含重复的名称,默认情况下 pandas
会将它们区分开,以防止数据覆盖
In [54]: data = "a,b,a\n0,1,2\n3,4,5"
In [55]: pd.read_csv(StringIO(data))
Out[55]:
a b a.1
0 0 1 2
1 3 4 5
默认情况下,mangle_dupe_cols=True
会使用 .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
异常:
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
usecols
参数允许你选择文件中指定的列,可以使用列名、位置或一个可调用的函数
In [56]: data = "a,b,c,d\n1,2,3,foo\n4,5,6,bar\n7,8,9,baz" In [57]: pd.read_csv(StringIO(data)) Out[57]: a b c d 0 1 2 3 foo 1 4 5 6 bar 2 7 8 9 baz In [58]: pd.read_csv(StringIO(data), usecols=["b", "d"]) Out[58]: b d 0 2 foo 1 5 bar 2 8 baz In [59]: pd.read_csv(StringIO(data), usecols=[0, 2, 3]) Out[59]: a c d 0 1 3 foo 1 4 6 bar 2 7 9 baz In [60]: pd.read_csv(StringIO(data), usecols=lambda x: x.upper() in ["A", "C"]) Out[60]: a c 0 1 3 1 4 6 2 7 9
usecols
参数还可以用于指定最终结果中不使用哪些列
In [61]: pd.read_csv(StringIO(data), usecols=lambda x: x not in ["a", "c"])
Out[61]:
b d
0 2 foo
1 5 bar
2 8 baz
在这个例子中,我们排除了 a
和 c
列
如果指定了 comment
参数,则注释的行将被忽略。默认情况下,空白的行也会被忽略
In [62]: data = "\na,b,c\n \n# commented line\n1,2,3\n\n4,5,6" In [63]: print(data) a,b,c # commented line 1,2,3 4,5,6 In [64]: pd.read_csv(StringIO(data), comment="#") Out[64]: a b c 0 1 2 3 1 4 5 6
如果设置 skip_blank_lines=False
,则不会忽略空行和注释行
In [65]: data = "a,b,c\n\n1,2,3\n\n\n4,5,6"
In [66]: pd.read_csv(StringIO(data), skip_blank_lines=False)
Out[66]:
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 [67]: data = "#comment\na,b,c\nA,B,C\n1,2,3"
In [68]: pd.read_csv(StringIO(data), comment="#", header=1)
Out[68]:
A B C
0 1 2 3
In [69]: data = "A,B,C\n#comment\na,b,c\n1,2,3"
In [70]: pd.read_csv(StringIO(data), comment="#", skiprows=2)
Out[70]:
a b c
0 1 2 3
如果 header
和 skiprows
都指定了,则 header
将相对于 skiprows
的末尾。例如
In [71]: data = ( ....: "# empty\n" ....: "# second empty line\n" ....: "# third emptyline\n" ....: "X,Y,Z\n" ....: "1,2,3\n" ....: "A,B,C\n" ....: "1,2.,4.\n" ....: "5.,NaN,10.0\n" ....: ) ....: In [72]: 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 [73]: pd.read_csv(StringIO(data), comment="#", skiprows=4, header=1) Out[73]: A B C 0 1.0 2.0 4.0 1 5.0 NaN 10.0
有时文件中可能包含注释或元数据:
In [74]: 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 [75]: df = pd.read_csv("tmp.csv")
In [76]: df
Out[76]:
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 [77]: df = pd.read_csv("tmp.csv", comment="#")
In [78]: df
Out[78]:
ID level category
0 Patient1 123000 x
1 Patient2 23000 y
2 Patient3 1234018 z
encoding
参数应用于编码 unicode
数据,它将导致字节字符串在结果中需要 unicode
解码
In [79]: from io import BytesIO In [80]: data = b"word,length\n" b"Tr\xc3\xa4umen,7\n" b"Gr\xc3\xbc\xc3\x9fe,5" In [81]: data = data.decode("utf8").encode("latin-1") In [82]: df = pd.read_csv(BytesIO(data), encoding="latin-1") In [83]: df Out[83]: word length 0 Träumen 7 1 Grüße 5 In [84]: df["word"][1] Out[84]: 'Grüße'
一些情况下必须指定正确的解码格式才能正确解析数据
如果一个文件的数据列比列名多一列,第一列将被用作 DataFrame
的行名
In [85]: data = "a,b,c\n4,apple,bat,5.7\n8,orange,cow,10"
In [86]: pd.read_csv(StringIO(data))
Out[86]:
a b c
4 apple bat 5.7
8 orange cow 10.0
In [87]: data = "index,a,b,c\n4,apple,bat,5.7\n8,orange,cow,10"
In [88]: pd.read_csv(StringIO(data), index_col=0)
Out[88]:
a b c
index
4 apple bat 5.7
8 orange cow 10.0
通常,您可以使用 index_col
参数来实现此行为
当在每个数据行的末尾带有一个分隔符的文件时,会出现一些异常情况,让解析器感到头大。要显式禁用索引列推断并放弃最后一列,可以设置 index_col=False
In [89]: data = "a,b,c\n4,apple,bat,\n8,orange,cow," In [90]: print(data) a,b,c 4,apple,bat, 8,orange,cow, In [91]: pd.read_csv(StringIO(data)) Out[91]: a b c 4 apple bat NaN 8 orange cow NaN In [92]: pd.read_csv(StringIO(data), index_col=False) Out[92]: a b c 0 4 apple bat 1 8 orange cow
如果使用 usecols
参数提取数据的子集,index_col
的作用将基于该子集,而不是原始数据
In [93]: data = "a,b,c\n4,apple,bat,\n8,orange,cow," In [94]: print(data) a,b,c 4,apple,bat, 8,orange,cow, In [95]: pd.read_csv(StringIO(data), usecols=["b", "c"]) Out[95]: b c 4 bat NaN 8 cow NaN In [96]: pd.read_csv(StringIO(data), usecols=["b", "c"], index_col=0) Out[96]: b c 4 bat NaN 8 cow NaN
注意:虽然使用了 usecols
参数,但是由于末尾的分隔符,导致数据的第一列作为索引而无法使数据正确对齐
为了更好地处理 datetime
数据,read_csv()
提供了 parse_dates
和 date_parser
关键字参数来指定日期/时间格式,以便将输入文本数据转换为 datetime
对象
最简单的一种情况是只传递 parse_dates=True
# Use a column as an index, and parse it as dates.
In [97]: df = pd.read_csv("foo.csv", index_col=0, parse_dates=True)
In [98]: df
Out[98]:
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 [99]: df.index
Out[99]: DatetimeIndex(['2009-01-01', '2009-01-02', '2009-01-03'], dtype='datetime64[ns]', name='date', freq=None)
通常情况下,我们可能希望单独存储日期和时间数据,或者单独存储各种日期字段。
parse_dates
参数可用于指定要从中解析日期和/或时间的列组合
您可以为 parse_dates
指定一组列,组合后的日期列将被添加到输出结果的前面(为了不影响现有的列顺序),新的列名将是以 _
连接的列名
In [100]: 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 [101]: df = pd.read_csv("tmp.csv", header=None, parse_dates=[[1, 2], [1, 3]]) In [102]: df Out[102]: 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 [103]: df = pd.read_csv(
.....: "tmp.csv", header=None, parse_dates=[[1, 2], [1, 3]], keep_date_col=True
.....: )
.....:
In [104]: df
Out[104]:
1_2 1_3 0 1 2 3 4
0 1999-01-27 19:00:00 1999-01-27 18:56:00 KORD 19990127 19:00:00 18:56:00 0.81
1 1999-01-27 20:00:00 1999-01-27 19:56:00 KORD 19990127 20:00:00 19:56:00 0.01
2 1999-01-27 21:00:00 1999-01-27 20:56:00 KORD 19990127 21:00:00 20:56:00 -0.59
3 1999-01-27 21:00:00 1999-01-27 21:18:00 KORD 19990127 21:00:00 21:18:00 -0.99
4 1999-01-27 22:00:00 1999-01-27 21:56:00 KORD 19990127 22:00:00 21:56:00 -0.59
5 1999-01-27 23:00:00 1999-01-27 22:56:00 KORD 19990127 23:00:00 22:56:00 -0.59
注意,如果您希望将多个列合并为一个日期列,则必须使用嵌套列表。
也就是说,parse_dates=[1,2]
表示第二和第三列应该分别解析为单独的日期列,而 parse_dates=[[1,2]]
表示这两列应该解析为一个单独的列
你也可以使用字典来自定义组合的名称列
In [105]: date_spec = {"nominal": [1, 2], "actual": [1, 3]}
In [106]: df = pd.read_csv("tmp.csv", header=None, parse_dates=date_spec)
In [107]: df
Out[107]:
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 [108]: date_spec = {"nominal": [1, 2], "actual": [1, 3]} In [109]: df = pd.read_csv( .....: "tmp.csv", header=None, parse_dates=date_spec, index_col=0 .....: ) # index is the nominal column .....: In [110]: df Out[110]: 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
注意:
如果列或索引包含无法解析的日期,则整个列或索引将不变地作为 object
数据类型返回。
对于非标准日期时间解析,请在 pd.read_csv
之后使用 to_datetime()
解析
解析器允许您指定一个自定义的 date_parser
函数,以充分利用日期解析 API
的灵活性
In [111]: df = pd.read_csv(
.....: "tmp.csv", header=None, parse_dates=date_spec, date_parser=pd.to_datetime
.....: )
.....:
In [112]: df
Out[112]:
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
函数。如果抛出异常,则尝试下一种方式
date_parser
首先使用一个或多个数组作为参数被调用,这些数组是使用 parse_dates
定义的(例如,date_parser(['2013', '2013'], ['1', '2'])
)
如果 1
失败了,则会调用 date_parser
,并将所有列按行连接到单个数组中(例如,date_parser(['2013 1','2013 2'])
)
注意,在性能方面,你应该尝试按以下顺序来解析日期
infer_datetime_format=True
来推断格式pd.to_datetime()
: date_parser=lambda x: pd.to_datetime(x, format=...)
date_parser
函数pandas
本身不能表示带有混合时区的列或索引。如果 CSV
文件包含混合时区的列,则默认结果将是一个字符串类型的列,即使使用了 parse_dates
也一样
In [113]: content = """\
.....: a
.....: 2000-01-01T00:00:00+05:00
.....: 2000-01-01T00:00:00+06:00"""
.....:
In [114]: df = pd.read_csv(StringIO(content), parse_dates=["a"])
In [115]: df["a"]
Out[115]:
0 2000-01-01 00:00:00+05:00
1 2000-01-01 00:00:00+06:00
Name: a, dtype: object
要将混合时区值解析为 datetime
类型,需要传递一个部分应用的 to_datetime()
,且设置参数 utc=True
作为 date_parser
In [116]: df = pd.read_csv(
.....: StringIO(content),
.....: parse_dates=["a"],
.....: date_parser=lambda col: pd.to_datetime(col, utc=True),
.....: )
.....:
In [117]: df["a"]
Out[117]:
0 1999-12-31 19:00:00+00:00
1 1999-12-31 18:00:00+00:00
Name: a, dtype: datetime64[ns, UTC]
如果您为部分或所有列启用了 parse_dates
,并且 datetime
字符串都是相同的格式,那么通过设置 infer_datetime_format=True
,可以大大提升解析速度。
如果无法猜测格式,或者猜测的格式不能正确解析整个字符串列,将会使用通用的解析方式
下面是一些可以猜测的 datetime
字符串的例子(都表示 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_format
对 dayfirst
敏感。如果 dayfirst=True
,它就会把 01/12/2011
认为是 12
月 1
日。dayfirst=False
(默认值)将把 01/12/2011
猜测为 1
月 12
日
# Try to infer the format for the index column In [118]: df = pd.read_csv( .....: "foo.csv", .....: index_col=0, .....: parse_dates=True, .....: infer_datetime_format=True, .....: ) .....: In [119]: df Out[119]: A B C date 2009-01-01 a 1 2 2009-01-02 b 3 4 2009-01-03 c 4 5
虽然美国的日期格式往往是 MM/DD/YYYY
,但许多国际格式使用 DD/MM/YYYY
代替。为方便起见,提供了 dayfirst
关键字
In [120]: print(open("tmp.csv").read()) date,value,cat 1/6/2000,5,a 2/6/2000,10,b 3/6/2000,15,c In [121]: pd.read_csv("tmp.csv", parse_dates=[0]) Out[121]: date value cat 0 2000-01-06 5 a 1 2000-02-06 10 b 2 2000-03-06 15 c In [122]: pd.read_csv("tmp.csv", dayfirst=True, parse_dates=[0]) Out[122]: date value cat 0 2000-06-01 5 a 1 2000-06-02 10 b 2 2000-06-03 15 c
df.to_csv(..., mode="wb")
允许将 CSV
写入打开的二进制模式的文件对象。
在大多数情况下,无需指定模式,因为 Pandas
会自动检测文件对象是以文本模式还是二进制模式打开的
In [123]: import io
In [124]: data = pd.DataFrame([0, 1, 2])
In [125]: buffer = io.BytesIO()
In [126]: data.to_csv(buffer, encoding="utf-8", compression="gzip")
可以在 C
引擎解析期间使用 float_precision
参数来指定浮点数转换器
该参数有三个可选的值:
None
: 普通转换器high
: 高精度转换器round_trip
: 保证文件读写之后小数点精度不变In [127]: val = "0.3066101993807095471566981359501369297504425048828125" In [128]: data = "a,b,c\n1,2,{0}".format(val) In [129]: abs( .....: pd.read_csv( .....: StringIO(data), .....: engine="c", .....: float_precision=None, .....: )["c"][0] - float(val) .....: ) .....: Out[129]: 5.551115123125783e-17 In [130]: abs( .....: pd.read_csv( .....: StringIO(data), .....: engine="c", .....: float_precision="high", .....: )["c"][0] - float(val) .....: ) .....: Out[130]: 5.551115123125783e-17 In [131]: abs( .....: pd.read_csv(StringIO(data), engine="c", float_precision="round_trip")["c"][0] .....: - float(val) .....: ) .....: Out[131]: 0.0
对于使用千位分隔符编写的大数,可以将千位关键字设置为长度为 1
的字符串,以便正确解析整数
而在默认情况下,带有千位分隔符的数字将被解析为字符串
In [132]: print(open("tmp.csv").read()) ID|level|category Patient1|123,000|x Patient2|23,000|y Patient3|1,234,018|z In [133]: df = pd.read_csv("tmp.csv", sep="|") In [134]: df Out[134]: ID level category 0 Patient1 123,000 x 1 Patient2 23,000 y 2 Patient3 1,234,018 z In [135]: df.level.dtype Out[135]: dtype('O')
可以设置 thousands
参数来解析
In [136]: print(open("tmp.csv").read()) ID|level|category Patient1|123,000|x Patient2|23,000|y Patient3|1,234,018|z In [137]: df = pd.read_csv("tmp.csv", sep="|", thousands=",") In [138]: df Out[138]: ID level category 0 Patient1 123000 x 1 Patient2 23000 y 2 Patient3 1234018 z In [139]: df.level.dtype Out[139]: dtype('int64')
要控制哪些值被解析为缺失值(用 NaN
表示),请在 na_values
中指定一个字符串。
如果指定了一个字符串列表,那么其中的所有值都被认为是缺失值
如果您指定一个数字(如浮点数 5.0
或整数 5
),相应的等效值也将被认为是一个缺失的值(在这种情况下 [5.0,5]
被有效地识别为 NaN
)。
要完全覆盖会被识别为缺失的默认值,请指定 keep_default_na=False
默认被识别为 NaN
的值是
['-1.#IND', '1.#QNAN', '1.#IND', '-1.#QNAN', '#N/A N/A', '#N/A', 'N/A', 'n/a', 'NA', '<NA>', '#NA', 'NULL', 'null', 'NaN', '-NaN', 'nan', '-nan', '']
考虑下面额例子
pd.read_csv("path_to_file.csv", na_values=[5])
在上述示例中,除了默认值之外,5
和 5.0
将被识别为 NaN
。字符串将首先被解释为数字 5
,然后被解释为 NaN
。
pd.read_csv("path_to_file.csv", keep_default_na=False, na_values=[""])
在上面的例子中,只有空白字段会被识别为 NaN
pd.read_csv("path_to_file.csv", keep_default_na=False, na_values=["NA", "0"])
上例中,字符串 NA
和 0
都会被识别为 NaN
pd.read_csv("path_to_file.csv", na_values=["Nope"])
除了默认值外,字符串 Nope
也会被识别为 NaN
inf
类似的值将被解析为 np.inf
(正无穷)和 -inf
为 -np.inf
(负无穷)。
解析会忽略值的大小写,即 Inf
,也将被解析为 np.inf
使用 squeeze
关键字参数,将返回单个列的 Series
形式输出:
In [140]: print(open("tmp.csv").read()) level Patient1,123000 Patient2,23000 Patient3,1234018 In [141]: output = pd.read_csv("tmp.csv", squeeze=True) In [142]: output Out[142]: Patient1 123000 Patient2 23000 Patient3 1234018 Name: level, dtype: int64 In [143]: type(output) Out[143]: pandas.core.series.Series
常见的值 True
和 False
都被认为是布尔值。有时您可能想要识别其他值为布尔值。
为此,可以使用 true_values
和 false_values
参数,如下所示:
In [144]: data = "a,b,c\n1,Yes,2\n3,No,4" In [145]: print(data) a,b,c 1,Yes,2 3,No,4 In [146]: pd.read_csv(StringIO(data)) Out[146]: a b c 0 1 Yes 2 1 3 No 4 In [147]: pd.read_csv(StringIO(data), true_values=["Yes"], false_values=["No"]) Out[147]: a b c 0 1 True 2 1 3 False 4
某些文件的行格式存在错误,字段太少或太多。字段太少的行将在尾随字段中填充 NA
值。默认情况下,包含太多字段的行将引发错误
In [148]: data = "a,b,c\n1,2,3\n4,5,6,7\n8,9,10" In [149]: pd.read_csv(StringIO(data)) --------------------------------------------------------------------------- ParserError Traceback (most recent call last) <ipython-input-5-6388c394e6b8> in <module> ----> 1 pd.read_csv(StringIO(data)) ~/opt/anaconda3/lib/python3.8/site-packages/pandas/io/parsers.py in read_csv(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, squeeze, prefix, mangle_dupe_cols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, dialect, error_bad_lines, warn_bad_lines, delim_whitespace, low_memory, memory_map, float_precision) 684 ) 685 --> 686 return _read(filepath_or_buffer, kwds) 687 688 ~/opt/anaconda3/lib/python3.8/site-packages/pandas/io/parsers.py in _read(filepath_or_buffer, kwds) 456 457 try: --> 458 data = parser.read(nrows) 459 finally: 460 parser.close() ~/opt/anaconda3/lib/python3.8/site-packages/pandas/io/parsers.py in read(self, nrows) 1194 def read(self, nrows=None): 1195 nrows = _validate_integer("nrows", nrows) -> 1196 ret = self._engine.read(nrows) 1197 1198 # May alter columns / col_dict ~/opt/anaconda3/lib/python3.8/site-packages/pandas/io/parsers.py in read(self, nrows) 2153 def read(self, nrows=None): 2154 try: -> 2155 data = self._reader.read(nrows) 2156 except StopIteration: 2157 if self._first_chunk: pandas/_libs/parsers.pyx in pandas._libs.parsers.TextReader.read() pandas/_libs/parsers.pyx in pandas._libs.parsers.TextReader._read_low_memory() pandas/_libs/parsers.pyx in pandas._libs.parsers.TextReader._read_rows() pandas/_libs/parsers.pyx in pandas._libs.parsers.TextReader._tokenize_rows() pandas/_libs/parsers.pyx in pandas._libs.parsers.raise_parser_error() ParserError: Error tokenizing data. C error: Expected 3 fields in line 3, saw 4
你可以选择跳过错误的行
In [29]: pd.read_csv(StringIO(data), error_bad_lines=False)
b'Skipping line 3: expected 3 fields, saw 4\n'
Out[29]:
a b c
0 1 2 3
1 8 9 10
你也可以使用 usecols
参数来消除某些行中出现的多余的列数据
In [30]: pd.read_csv(StringIO(data), usecols=[0, 1, 2])
Out[30]:
a b c
0 1 2 3
1 4 5 6
2 8 9 10
dialect
参数在读取特定格式的文件时提供了更大的灵活性,默认情况下,它使用 Excel
方言,但您可以指定方言名称或 csv.Dialect
实例
假设您的数据带有未封闭的引号
In [150]: print(data)
label1,label2,label3
index1,"a,c,e
index2,b,d,f
默认情况下,read_csv
使用 Excel
方言,并将双引号视为引号字符,这会导致在换行符之前无法找到配对的双引号。
我们可以用 dialect
来解决这个问题:
In [151]: import csv
In [152]: dia = csv.excel()
In [153]: dia.quoting = csv.QUOTE_NONE
In [154]: pd.read_csv(StringIO(data), dialect=dia)
Out[154]:
label1 label2 label3
index1 "a c e
index2 b d f
可以通过关键字参数分别指定所有方言选项
In [155]: data = "a,b,c~1,2,3~4,5,6"
In [156]: pd.read_csv(StringIO(data), lineterminator="~")
Out[156]:
a b c
0 1 2 3
1 4 5 6
另一个常见的方言选项是 skipinitialspace
,跳过分隔符后的任何空白字符
In [157]: data = "a, b, c\n1, 2, 3\n4, 5, 6"
In [158]: print(data)
a, b, c
1, 2, 3
4, 5, 6
In [159]: pd.read_csv(StringIO(data), skipinitialspace=True)
Out[159]:
a b c
0 1 2 3
1 4 5 6
解析器会尽一切努力做正确的事情,类型推断非常重要
嵌入字段中的引号(和其他转义字符)可以通过多种方式处理。
一种方法是使用反斜杠。要正确解析此数据,您应该传递 escapechar
选项:
In [160]: data = 'a,b\n"hello, \\"Bob\\", nice to see you",5'
In [161]: print(data)
a,b
"hello, \"Bob\", nice to see you",5
In [162]: pd.read_csv(StringIO(data), escapechar="\\")
Out[162]:
a b
0 hello, "Bob", nice to see you 5
read_fwf()
函数可用于读取具有固定列宽的数据文件
read_fwf
的函数参数与 read_csv
的函数参数基本相同,只是有两个额外的参数,而且 delimiter
参数的用法也不同:
colspecs
:一个元组列表,给出每行固定宽度字段的范围,半开区间。默认设置为 infer
可以让解析器自动从数据的前 100
行中推断出格式。widths
:一个字段宽度列表,如果间隔是连续的,可以用它来代替 colspecs
delimiter
:在固定宽度的文件中作为填充字符。如 ~
考虑如下固定宽度文件
In [163]: 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 [164]: colspecs = [(0, 6), (8, 20), (21, 33), (34, 43)]
In [165]: df = pd.read_fwf("bar.csv", colspecs=colspecs, header=None, index_col=0)
In [166]: df
Out[166]:
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
另外,您可以仅提供连续列的列宽:
# Widths are a list of integers
In [167]: widths = [6, 14, 13, 10]
In [168]: df = pd.read_fwf("bar.csv", widths=widths, header=None)
In [169]: df
Out[169]:
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
解析器会忽略列周围的多余空白,因此可以在文件中的列之间留出额外的分隔。
默认情况下,read_fwf
会尝试使用文件的前 100
行来推断文件的 colspec
。
仅当文件的列能够通过提供的定界符对齐并正确分隔时,才可以这样做
In [170]: df = pd.read_fwf("bar.csv", header=None, index_col=0)
In [171]: df
Out[171]:
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
read_fwf
支持 dtype
参数,用于指定与推断类型不同的列类型
In [172]: pd.read_fwf("bar.csv", header=None, index_col=0).dtypes
Out[172]:
1 float64
2 float64
3 float64
dtype: object
In [173]: pd.read_fwf("bar.csv", header=None, dtype={2: "object"}).dtypes
Out[173]:
0 object
1 float64
2 object
3 float64
dtype: object
考虑下面这个文件,表头的数量比数据列的数量少一个
In [174]: print(open("foo.csv").read())
A,B,C
20090101,a,1,2
20090102,b,3,4
20090103,c,4,5
在这种情况下,read_csv
假定第一列数据将作为 DataFrame
的索引
In [175]: pd.read_csv("foo.csv")
Out[175]:
A B C
20090101 a 1 2
20090102 b 3 4
20090103 c 4 5
注意: 在这种情况下,日期不会自动解析,你需要像以前一样指定参数
In [176]: df = pd.read_csv("foo.csv", parse_dates=True)
In [177]: df.index
Out[177]: DatetimeIndex(['2009-01-01', '2009-01-02', '2009-01-03'], dtype='datetime64[ns]', freq=None)
假设您有两列索引的数据
In [178]: 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
可以使用 index_col
参数传递一个列索引列表,以将多个列组合为多重索引
In [179]: df = pd.read_csv("data/mindex_ex.csv", index_col=[0, 1]) In [180]: df Out[180]: 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 [181]: df.loc[1978] Out[181]: 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
通过为 header
参数指定行号列表,您可以将列表中读取的行作为列的多级索引。
如果指定了非连续的行,将会跳过中间的行
In [182]: from pandas._testing import makeCustomDataframe as mkdf In [183]: df = mkdf(5, 3, r_idx_nlevels=2, c_idx_nlevels=4) In [184]: df.to_csv("mi.csv") In [185]: 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 [186]: pd.read_csv("mi.csv", header=[0, 1, 2, 3], index_col=[0, 1]) Out[186]: 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
read_csv
还能够解析一种更常见的多列索引格式
,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 [188]: pd.read_csv("mi2.csv", header=[0, 1], index_col=0)
Out[188]:
a b c
q r s t u v
one 1 2 3 4 5 6
two 7 8 9 10 11 12
注意: 如果没有指定 index_col
(例如,数据没有索引),那么列索引上的列名都会丢失
read_csv
能够推断出文件的分隔符,因为 pandas 使用了 csv
模块的 csv.Sniffer
类。为此,你必须指定 sep=None
。
In [189]: print(open("tmp2.sv").read()) :0:1:2:3 0:0.4691122999071863:-0.2828633443286633:-1.5090585031735124:-1.1356323710171934 1:1.2121120250208506:-0.17321464905330858:0.11920871129693428:-1.0442359662799567 2:-0.8618489633477999:-2.1045692188948086:-0.4949292740687813:1.071803807037338 3:0.7215551622443669:-0.7067711336300845:-1.0395749851146963:0.27185988554282986 4:-0.42497232978883753:0.567020349793672:0.27623201927771873:-1.0874006912859915 5:-0.6736897080883706:0.1136484096888855:-1.4784265524372235:0.5249876671147047 6:0.4047052186802365:0.5770459859204836:-1.7150020161146375:-1.0392684835147725 7:-0.3706468582364464:-1.1578922506419993:-1.344311812731667:0.8448851414248841 8:1.0757697837155533:-0.10904997528022223:1.6435630703622064:-1.4693879595399115 9:0.35702056413309086:-0.6746001037299882:-1.776903716971867:-0.9689138124473498 In [190]: pd.read_csv("tmp2.sv", sep=None, engine="python") Out[190]: 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
假设你希望惰性地遍历一个(可能非常大的)文件,而不是一次性将整个文件读入内存
例如,有如下文件
In [191]: print(open("tmp.sv").read()) |0|1|2|3 0|0.4691122999071863|-0.2828633443286633|-1.5090585031735124|-1.1356323710171934 1|1.2121120250208506|-0.17321464905330858|0.11920871129693428|-1.0442359662799567 2|-0.8618489633477999|-2.1045692188948086|-0.4949292740687813|1.071803807037338 3|0.7215551622443669|-0.7067711336300845|-1.0395749851146963|0.27185988554282986 4|-0.42497232978883753|0.567020349793672|0.27623201927771873|-1.0874006912859915 5|-0.6736897080883706|0.1136484096888855|-1.4784265524372235|0.5249876671147047 6|0.4047052186802365|0.5770459859204836|-1.7150020161146375|-1.0392684835147725 7|-0.3706468582364464|-1.1578922506419993|-1.344311812731667|0.8448851414248841 8|1.0757697837155533|-0.10904997528022223|1.6435630703622064|-1.4693879595399115 9|0.35702056413309086|-0.6746001037299882|-1.776903716971867|-0.9689138124473498 In [192]: table = pd.read_csv("tmp.sv", sep="|") In [193]: table Out[193]: 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
通过为 read_csv
指定 chunksize
,将会返回 TextFileReader
类型的可迭代对象:
In [194]: with pd.read_csv("tmp.sv", sep="|", chunksize=4) as reader: .....: reader .....: 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 [195]: with pd.read_csv("tmp.sv", sep="|", iterator=True) as reader:
.....: reader.get_chunk(5)
pandas
有两个解析器:
C
语言实现的快速高效的解析器Python
实现的功能更加完善的解析器pandas
尽可能使用 C
解析器,但是如果指定了 C
不支持的选项,将会使用 Python
解析器。
C
不支持的选项包括:
sep
:除了单字符之外,如,正则表达式skipfooter
:sep=Non
e 且 delim_whitespace=False
除非使用 engine ='python'
明确选择 python
引擎,否则指定以上任何选项都将产生 ParserWarning
您可以传入一个 URL
来读取或写入远程文件,以下示例显示读取 CSV
文件:
df = pd.read_csv("https://download.bls.gov/pub/time.series/cu/cu.item", sep="\t")
Series
和 DataFrame
对象都有 to_csv
方法,该方法允许将对象的内容存储为逗号分隔文件。
该函数带有多个参数。只有第一个是必须的
path_or_buf
: 要写入文件的路径或文件对象,如果是文件对象,必须使用 newline=''
sep
: 输出文件的字段分隔符 (默认为 ,
)na_rep
: 缺失值的字符串表示形式(默认为 ''
)float_format
: 浮点数的格式化字符串columns
: 要写入的列 (默认为 None
)header
: 是否写出列名 (默认 True
)index
: 是否写出索引名 (默认 True
)index_label
: 索引列的列名,默认为 None
,并且 header
和 index
为 True
,则使用索引名称。如果 DataFrame
使用 MultiIndex
,则应给出一个序列mode
: Python
写入模式,默认 'w'
encoding
: 字符串编码格式line_terminator
: 表示行尾的字符序列(默认 os.linesep
)quoting
: 在 csv
模块中设置引用规则(默认为 csv.QUOTE_MINIMAL
)。注意:如果您设置了 float_format
,那么浮点数将被转换为字符串,csv.QUOTE_NONNUMERIC
将它们视为非数字quotechar
: 用于引用字段的字符(默认 "
)doublequote
: 控制字段中 quotechar
的引用 (默认 True
)escapechar
: 在适当时用于转义 sep
和 quotechar
的字符(默认 None
)chunksize
: 一次写入的行数date_format
: datetime
对象的格式化字符串DataFrame
对象具有 to_string
实例方法,该方法允许控制对象的字符串表示形式。所有参数都是可选的
buf
: 默认为 None
,例如一个 StringIO
对象columns
: 默认为 None
, 要写入的列col_space
: 默认为 None
,每列的最小宽度。na_rep
: 默认为 NaN
, NA
值的表示formatters
: 默认为 None
, 一个函数的字典(按列),每个函数接受一个参数并返回一个格式化的字符串。float_format
: 默认为 None
, 一个带有单个(浮点)参数并返回格式化字符串的函数;应用于 DataFrame
中的浮点数sparsify
: 默认为 True
, 对于具有层次结构索引的 DataFrame
,将其设置为 False
可在每一行打印每个 MultiIndex
键index_names
: 默认为 True
, 将打印索引名index
: 默认为 True
, 打印索引header
: 默认为 True
, 打印列名justify
: 默认 left
, 列左对齐或右对齐Series
对象也有一个 to_string
方法,但是只有 buf
、na_rep
、float_format
参数。
还有一个 length
参数,如果设置为 True
,将额外输出序列的长度
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。