Pandas 2.2 中文官方教程和指南(十·二)(3)https://developer.aliyun.com/article/1509788
国际日期格式
美国的日期格式通常是 MM/DD/YYYY,而许多国际格式则使用 DD/MM/YYYY。为了方便起见,提供了一个 dayfirst 关键字:
In [134]: data = "date,value,cat\n1/6/2000,5,a\n2/6/2000,10,b\n3/6/2000,15,c" In [135]: print(data) date,value,cat 1/6/2000,5,a 2/6/2000,10,b 3/6/2000,15,c In [136]: with open("tmp.csv", "w") as fh: .....: fh.write(data) .....: In [137]: pd.read_csv("tmp.csv", parse_dates=[0]) Out[137]: date value cat 0 2000-01-06 5 a 1 2000-02-06 10 b 2 2000-03-06 15 c In [138]: pd.read_csv("tmp.csv", dayfirst=True, parse_dates=[0]) Out[138]: date value cat 0 2000-06-01 5 a 1 2000-06-02 10 b 2 2000-06-03 15 c
将 CSV 写入二进制文件对象
新版本 1.2.0 中新增。
df.to_csv(..., mode="wb") 允许将 CSV 写入以二进制模式打开的文件对象。在大多数情况下,不需要指定 mode,因为 Pandas 将自动检测文件对象是以文本模式还是二进制模式打开的。
In [139]: import io In [140]: data = pd.DataFrame([0, 1, 2]) In [141]: buffer = io.BytesIO() In [142]: data.to_csv(buffer, encoding="utf-8", compression="gzip") ```### 指定浮点转换方法 可以通过指定 `float_precision` 参数来使用特定的浮点数转换器在 C 引擎解析时。选项有普通转换器、高精度转换器和往返转换器(保证在写入文件后循环的值)。例如: ```py In [143]: val = "0.3066101993807095471566981359501369297504425048828125" In [144]: data = "a,b,c\n1,2,{0}".format(val) In [145]: abs( .....: pd.read_csv( .....: StringIO(data), .....: engine="c", .....: float_precision=None, .....: )["c"][0] - float(val) .....: ) .....: Out[145]: 5.551115123125783e-17 In [146]: abs( .....: pd.read_csv( .....: StringIO(data), .....: engine="c", .....: float_precision="high", .....: )["c"][0] - float(val) .....: ) .....: Out[146]: 5.551115123125783e-17 In [147]: abs( .....: pd.read_csv(StringIO(data), engine="c", float_precision="round_trip")["c"][0] .....: - float(val) .....: ) .....: Out[147]: 0.0 ```### 千位分隔符 对于以千位分隔符编写的大数字,您可以将 `thousands` 关键字设置为长度为 1 的字符串,以便正确解析整数: 默认情况下,带有千位分隔符的数字将被解析为字符串: ```py In [148]: data = ( .....: "ID|level|category\n" .....: "Patient1|123,000|x\n" .....: "Patient2|23,000|y\n" .....: "Patient3|1,234,018|z" .....: ) .....: In [149]: with open("tmp.csv", "w") as fh: .....: fh.write(data) .....: In [150]: df = pd.read_csv("tmp.csv", sep="|") In [151]: df Out[151]: ID level category 0 Patient1 123,000 x 1 Patient2 23,000 y 2 Patient3 1,234,018 z In [152]: df.level.dtype Out[152]: dtype('O')
thousands 关键字允许正确解析整数:
In [153]: df = pd.read_csv("tmp.csv", sep="|", thousands=",") In [154]: df Out[154]: ID level category 0 Patient1 123000 x 1 Patient2 23000 y 2 Patient3 1234018 z In [155]: df.level.dtype Out[155]: dtype('int64') ```### NA 值 要控制哪些值被解析为缺失值(用 `NaN` 表示),请在 `na_values` 中指定一个字符串。如果您指定了一个字符串列表,那么其中的所有值都将被视为缺失值。如果您指定了一个数字(一个 `float`,比如 `5.0` 或一个 `integer`,比如 `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', 'None', '']`。 让我们考虑一些例子: ```py 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。 ### 布尔值
常见的值 True、False、TRUE 和 FALSE 都被识别为布尔值。偶尔你可能想要识别其他值为布尔值。为此,请使用如下所示的 true_values 和 false_values 选项:
In [156]: data = "a,b,c\n1,Yes,2\n3,No,4" In [157]: print(data) a,b,c 1,Yes,2 3,No,4 In [158]: pd.read_csv(StringIO(data)) Out[158]: a b c 0 1 Yes 2 1 3 No 4 In [159]: pd.read_csv(StringIO(data), true_values=["Yes"], false_values=["No"]) Out[159]: a b c 0 1 True 2 1 3 False 4 ```### 处理“坏”行 一些文件可能存在字段过少或过多的格式不正确的行。字段过少的行将在尾部字段中填充 NA 值。字段过多的行将默认引发错误: ```py In [160]: data = "a,b,c\n1,2,3\n4,5,6,7\n8,9,10" In [161]: pd.read_csv(StringIO(data)) --------------------------------------------------------------------------- ParserError Traceback (most recent call last) Cell In[161], line 1 ----> 1 pd.read_csv(StringIO(data)) File ~/work/pandas/pandas/pandas/io/parsers/readers.py:1026, in read_csv(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, 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, date_format, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, encoding_errors, dialect, on_bad_lines, delim_whitespace, low_memory, memory_map, float_precision, storage_options, dtype_backend) 1013 kwds_defaults = _refine_defaults_read( 1014 dialect, 1015 delimiter, (...) 1022 dtype_backend=dtype_backend, 1023 ) 1024 kwds.update(kwds_defaults) -> 1026 return _read(filepath_or_buffer, kwds) File ~/work/pandas/pandas/pandas/io/parsers/readers.py:626, in _read(filepath_or_buffer, kwds) 623 return parser 625 with parser: --> 626 return parser.read(nrows) File ~/work/pandas/pandas/pandas/io/parsers/readers.py:1923, in TextFileReader.read(self, nrows) 1916 nrows = validate_integer("nrows", nrows) 1917 try: 1918 # error: "ParserBase" has no attribute "read" 1919 ( 1920 index, 1921 columns, 1922 col_dict, -> 1923 ) = self._engine.read( # type: ignore[attr-defined] 1924 nrows 1925 ) 1926 except Exception: 1927 self.close() File ~/work/pandas/pandas/pandas/io/parsers/c_parser_wrapper.py:234, in CParserWrapper.read(self, nrows) 232 try: 233 if self.low_memory: --> 234 chunks = self._reader.read_low_memory(nrows) 235 # destructive to chunks 236 data = _concatenate_chunks(chunks) File parsers.pyx:838, in pandas._libs.parsers.TextReader.read_low_memory() File parsers.pyx:905, in pandas._libs.parsers.TextReader._read_rows() File parsers.pyx:874, in pandas._libs.parsers.TextReader._tokenize_rows() File parsers.pyx:891, in pandas._libs.parsers.TextReader._check_tokenize_status() File parsers.pyx:2061, in pandas._libs.parsers.raise_parser_error() ParserError: Error tokenizing data. C error: Expected 3 fields in line 3, saw 4
您可以选择跳过错误行:
In [162]: data = "a,b,c\n1,2,3\n4,5,6,7\n8,9,10" In [163]: pd.read_csv(StringIO(data), on_bad_lines="skip") Out[163]: a b c 0 1 2 3 1 8 9 10
版本 1.4.0 中的新功能。
或者在engine="python"时传递一个可调用函数来处理错误行。错误行将是由sep分割的字符串列表:
In [164]: external_list = [] In [165]: def bad_lines_func(line): .....: external_list.append(line) .....: return line[-3:] .....: In [166]: external_list Out[166]: []
注意
可调用函数仅处理字段过多的行。由其他错误引起的错误行将被静默跳过。
In [167]: bad_lines_func = lambda line: print(line) In [168]: data = 'name,type\nname a,a is of type a\nname b,"b\" is of type b"' In [169]: data Out[169]: 'name,type\nname a,a is of type a\nname b,"b" is of type b"' In [170]: pd.read_csv(StringIO(data), on_bad_lines=bad_lines_func, engine="python") Out[170]: name type 0 name a a is of type a
在这种情况下,该行未被处理,因为这里的“错误行”是由转义字符引起的。
您还可以使用usecols参数消除一些行中出现但其他行中不存在的多余列数据:
In [171]: pd.read_csv(StringIO(data), usecols=[0, 1, 2]) --------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In[171], line 1 ----> 1 pd.read_csv(StringIO(data), usecols=[0, 1, 2]) File ~/work/pandas/pandas/pandas/io/parsers/readers.py:1026, in read_csv(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, 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, date_format, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, encoding_errors, dialect, on_bad_lines, delim_whitespace, low_memory, memory_map, float_precision, storage_options, dtype_backend) 1013 kwds_defaults = _refine_defaults_read( 1014 dialect, 1015 delimiter, (...) 1022 dtype_backend=dtype_backend, 1023 ) 1024 kwds.update(kwds_defaults) -> 1026 return _read(filepath_or_buffer, kwds) File ~/work/pandas/pandas/pandas/io/parsers/readers.py:620, in _read(filepath_or_buffer, kwds) 617 _validate_names(kwds.get("names", None)) 619 # Create the parser. --> 620 parser = TextFileReader(filepath_or_buffer, **kwds) 622 if chunksize or iterator: 623 return parser File ~/work/pandas/pandas/pandas/io/parsers/readers.py:1620, in TextFileReader.__init__(self, f, engine, **kwds) 1617 self.options["has_index_names"] = kwds["has_index_names"] 1619 self.handles: IOHandles | None = None -> 1620 self._engine = self._make_engine(f, self.engine) File ~/work/pandas/pandas/pandas/io/parsers/readers.py:1898, in TextFileReader._make_engine(self, f, engine) 1895 raise ValueError(msg) 1897 try: -> 1898 return mappingengine 1899 except Exception: 1900 if self.handles is not None: File ~/work/pandas/pandas/pandas/io/parsers/c_parser_wrapper.py:155, in CParserWrapper.__init__(self, src, **kwds) 152 # error: Cannot determine type of 'names' 153 if len(self.names) < len(usecols): # type: ignore[has-type] 154 # error: Cannot determine type of 'names' --> 155 self._validate_usecols_names( 156 usecols, 157 self.names, # type: ignore[has-type] 158 ) 160 # error: Cannot determine type of 'names' 161 self._validate_parse_dates_presence(self.names) # type: ignore[has-type] File ~/work/pandas/pandas/pandas/io/parsers/base_parser.py:979, in ParserBase._validate_usecols_names(self, usecols, names) 977 missing = [c for c in usecols if c not in names] 978 if len(missing) > 0: --> 979 raise ValueError( 980 f"Usecols do not match columns, columns expected but not found: " 981 f"{missing}" 982 ) 984 return usecols ValueError: Usecols do not match columns, columns expected but not found: [0, 1, 2]
如果您希望保留所有数据,包括字段过多的行,可以指定足够数量的names。这样可以确保字段不足的行填充为NaN。
In [172]: pd.read_csv(StringIO(data), names=['a', 'b', 'c', 'd']) Out[172]: a b c d 0 name type NaN NaN 1 name a a is of type a NaN NaN 2 name b b is of type b" NaN NaN ```### 方言 `dialect`关键字提供了更大的灵活性来指定文件格式。默认情况下使用 Excel 方言,但您可以指定方言名称或[`csv.Dialect`](https://docs.python.org/3/library/csv.html#csv.Dialect "(在 Python v3.12 中)")实例。 假设您的数据中有未封闭的引号: ```py In [173]: data = "label1,label2,label3\n" 'index1,"a,c,e\n' "index2,b,d,f" In [174]: print(data) label1,label2,label3 index1,"a,c,e index2,b,d,f
默认情况下,read_csv使用 Excel 方言,并将双引号视为引号字符,这会导致在找到关闭双引号之前找到换行符时失败。
我们可以使用dialect来解决这个问题:
In [175]: import csv In [176]: dia = csv.excel() In [177]: dia.quoting = csv.QUOTE_NONE In [178]: pd.read_csv(StringIO(data), dialect=dia) Out[178]: label1 label2 label3 index1 "a c e index2 b d f
所有方言选项都可以通过关键字参数单独指定:
In [179]: data = "a,b,c~1,2,3~4,5,6" In [180]: pd.read_csv(StringIO(data), lineterminator="~") Out[180]: a b c 0 1 2 3 1 4 5 6
另一个常见的方言选项是skipinitialspace,用于跳过分隔符后的任何空格:
In [181]: data = "a, b, c\n1, 2, 3\n4, 5, 6" In [182]: print(data) a, b, c 1, 2, 3 4, 5, 6 In [183]: pd.read_csv(StringIO(data), skipinitialspace=True) Out[183]: a b c 0 1 2 3 1 4 5 6
解析器会尽力“做正确的事情”而不会变得脆弱。类型推断是一件很重要的事情。如果可以将列强制转换为整数 dtype 而不改变内容,则解析器将这样做。任何非数字列将像其他 pandas 对象一样以 object dtype 传递。 ### 引用和转义字符
嵌入字段中的引号(和其他转义字符)可以以多种方式处理。一种方法是使用反斜杠;为了正确解析这些数据,您应该传递escapechar选项:
In [184]: data = 'a,b\n"hello, \\"Bob\\", nice to see you",5' In [185]: print(data) a,b "hello, \"Bob\", nice to see you",5 In [186]: pd.read_csv(StringIO(data), escapechar="\\") Out[186]: a b 0 hello, "Bob", nice to see you 5 ```### 具有固定宽度列的文件 虽然`read_csv()`用于读取分隔数据,`read_fwf()`函数用于处理具有已知和固定列宽的数据文件。`read_fwf`的函数参数与`read_csv`基本相同,但有两个额外参数,并且`delimiter`参数的使用方式不同: + `colspecs`:一个对给出每行固定宽度字段的范围的一半开放区间(即,[from, to[)的列表(元组)。字符串值‘infer’ 可以用于指示解析器尝试从数据的前 100 行检测列规格。如果未指定,默认行为是推断。 + `widths`:一个字段宽度的列表,可用于代替‘colspecs’,如果间隔是连续的。 + `delimiter`:在固定宽度文件中视为填充字符的字符。如果字段的填充字符不是空格(例如,‘~’),则可以用它来指定字段的填充字符。 考虑一个典型的固定宽度数据文件: ```py In [187]: data1 = ( .....: "id8141 360.242940 149.910199 11950.7\n" .....: "id1594 444.953632 166.985655 11788.4\n" .....: "id1849 364.136849 183.628767 11806.2\n" .....: "id1230 413.836124 184.375703 11916.8\n" .....: "id1948 502.953953 173.237159 12468.3" .....: ) .....: In [188]: with open("bar.csv", "w") as f: .....: f.write(data1) .....:
为了将此文件解析为 DataFrame,我们只需提供列规格到 read_fwf 函数以及文件名:
# Column specifications are a list of half-intervals In [189]: colspecs = [(0, 6), (8, 20), (21, 33), (34, 43)] In [190]: df = pd.read_fwf("bar.csv", colspecs=colspecs, header=None, index_col=0) In [191]: df Out[191]: 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
注意当指定了 header=None 参数时,解析器会自动选择列名 X.<列编号>。或者,您可以仅提供连续列的列宽:
# Widths are a list of integers In [192]: widths = [6, 14, 13, 10] In [193]: df = pd.read_fwf("bar.csv", widths=widths, header=None) In [194]: df Out[194]: 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 行推断文件的 colspecs。它只能在列对齐且由提供的 delimiter(默认分隔符是空格)正确分隔的情况下进行。
In [195]: df = pd.read_fwf("bar.csv", header=None, index_col=0) In [196]: df Out[196]: 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 [197]: pd.read_fwf("bar.csv", header=None, index_col=0).dtypes Out[197]: 1 float64 2 float64 3 float64 dtype: object In [198]: pd.read_fwf("bar.csv", header=None, dtype={2: "object"}).dtypes Out[198]: 0 object 1 float64 2 object 3 float64 dtype: object
索引
带有“隐式”索引列的文件
考虑文件中标题项比数据列数少一个的情况:
In [199]: data = "A,B,C\n20090101,a,1,2\n20090102,b,3,4\n20090103,c,4,5" In [200]: print(data) A,B,C 20090101,a,1,2 20090102,b,3,4 20090103,c,4,5 In [201]: with open("foo.csv", "w") as f: .....: f.write(data) .....:
在这种特殊情况下,read_csv 假设第一列将用作 DataFrame 的索引:
In [202]: pd.read_csv("foo.csv") Out[202]: A B C 20090101 a 1 2 20090102 b 3 4 20090103 c 4 5
请注意,日期没有被自动解析。在这种情况下,您需要像以前一样操作:
In [203]: df = pd.read_csv("foo.csv", parse_dates=True) In [204]: df.index Out[204]: DatetimeIndex(['2009-01-01', '2009-01-02', '2009-01-03'], dtype='datetime64[ns]', freq=None)
使用 MultiIndex 读取索引
假设您的数据由两列索引:
In [205]: data = 'year,indiv,zit,xit\n1977,"A",1.2,.6\n1977,"B",1.5,.5' In [206]: print(data) year,indiv,zit,xit 1977,"A",1.2,.6 1977,"B",1.5,.5 In [207]: with open("mindex_ex.csv", mode="w") as f: .....: f.write(data) .....:
read_csv 的 index_col 参数可以接受列号列表,将多个列转换为返回对象的索引的 MultiIndex:
In [208]: df = pd.read_csv("mindex_ex.csv", index_col=[0, 1]) In [209]: df Out[209]: zit xit year indiv 1977 A 1.2 0.6 B 1.5 0.5 In [210]: df.loc[1977] Out[210]: zit xit indiv A 1.2 0.6 B 1.5 0.5
使用 MultiIndex 读取列
通过为 header 参数指定行位置列表,您可以读取列的 MultiIndex。指定非连续行将跳过介于其间的行。
In [211]: mi_idx = pd.MultiIndex.from_arrays([[1, 2, 3, 4], list("abcd")], names=list("ab")) In [212]: mi_col = pd.MultiIndex.from_arrays([[1, 2], list("ab")], names=list("cd")) In [213]: df = pd.DataFrame(np.ones((4, 2)), index=mi_idx, columns=mi_col) In [214]: df.to_csv("mi.csv") In [215]: print(open("mi.csv").read()) c,,1,2 d,,a,b a,b,, 1,a,1.0,1.0 2,b,1.0,1.0 3,c,1.0,1.0 4,d,1.0,1.0 In [216]: pd.read_csv("mi.csv", header=[0, 1, 2, 3], index_col=[0, 1]) Out[216]: c 1 2 d a b a Unnamed: 2_level_2 Unnamed: 3_level_2 1 1.0 1.0 2 b 1.0 1.0 3 c 1.0 1.0 4 d 1.0 1.0
read_csv 还能够解释更常见的多列索引格式。
In [217]: data = ",a,a,a,b,c,c\n,q,r,s,t,u,v\none,1,2,3,4,5,6\ntwo,7,8,9,10,11,12" In [218]: print(data) ,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 [219]: with open("mi2.csv", "w") as fh: .....: fh.write(data) .....: In [220]: pd.read_csv("mi2.csv", header=[0, 1], index_col=0) Out[220]: 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(例如,您没有索引,或者用 df.to_csv(..., index=False) 写入了它,则列索引上的任何 names 将会 丢失。### 自动“嗅探”定界符
read_csv 能够推断分隔(不一定是逗号分隔)的文件,因为 pandas 使用 csv 模块的 csv.Sniffer 类。为此,您必须指定 sep=None。
In [221]: df = pd.DataFrame(np.random.randn(10, 4)) In [222]: df.to_csv("tmp2.csv", sep=":", index=False) In [223]: pd.read_csv("tmp2.csv", sep=None, engine="python") Out[223]: 0 1 2 3 0 0.469112 -0.282863 -1.509059 -1.135632 1 1.212112 -0.173215 0.119209 -1.044236 2 -0.861849 -2.104569 -0.494929 1.071804 3 0.721555 -0.706771 -1.039575 0.271860 4 -0.424972 0.567020 0.276232 -1.087401 5 -0.673690 0.113648 -1.478427 0.524988 6 0.404705 0.577046 -1.715002 -1.039268 7 -0.370647 -1.157892 -1.344312 0.844885 8 1.075770 -0.109050 1.643563 -1.469388 9 0.357021 -0.674600 -1.776904 -0.968914 ```### 读取多个文件以创建单个 DataFrame 最好使用`concat()`来合并多个文件。查看 cookbook 以获取示例。 ### 逐块迭代文件 假设您希望惰性地迭代(可能非常大的)文件,而不是将整个文件读入内存,例如以下内容: ```py In [224]: df = pd.DataFrame(np.random.randn(10, 4)) In [225]: df.to_csv("tmp.csv", index=False) In [226]: table = pd.read_csv("tmp.csv") In [227]: table Out[227]: 0 1 2 3 0 -1.294524 0.413738 0.276662 -0.472035 1 -0.013960 -0.362543 -0.006154 -0.923061 2 0.895717 0.805244 -1.206412 2.565646 3 1.431256 1.340309 -1.170299 -0.226169 4 0.410835 0.813850 0.132003 -0.827317 5 -0.076467 -1.187678 1.130127 -1.436737 6 -1.413681 1.607920 1.024180 0.569605 7 0.875906 -2.211372 0.974466 -2.006747 8 -0.410001 -0.078638 0.545952 -1.219217 9 -1.226825 0.769804 -1.281247 -0.727707
通过在read_csv中指定chunksize,返回值将是一个TextFileReader类型的可迭代对象:
In [228]: with pd.read_csv("tmp.csv", chunksize=4) as reader: .....: print(reader) .....: for chunk in reader: .....: print(chunk) .....: <pandas.io.parsers.readers.TextFileReader object at 0x7ff2e5421db0> 0 1 2 3 0 -1.294524 0.413738 0.276662 -0.472035 1 -0.013960 -0.362543 -0.006154 -0.923061 2 0.895717 0.805244 -1.206412 2.565646 3 1.431256 1.340309 -1.170299 -0.226169 0 1 2 3 4 0.410835 0.813850 0.132003 -0.827317 5 -0.076467 -1.187678 1.130127 -1.436737 6 -1.413681 1.607920 1.024180 0.569605 7 0.875906 -2.211372 0.974466 -2.006747 0 1 2 3 8 -0.410001 -0.078638 0.545952 -1.219217 9 -1.226825 0.769804 -1.281247 -0.727707
从版本 1.2 开始更改:read_csv/json/sas 在遍历文件时返回一个上下文管理器。
指定iterator=True还将返回TextFileReader对象:
In [229]: with pd.read_csv("tmp.csv", iterator=True) as reader: .....: print(reader.get_chunk(5)) .....: 0 1 2 3 0 -1.294524 0.413738 0.276662 -0.472035 1 -0.013960 -0.362543 -0.006154 -0.923061 2 0.895717 0.805244 -1.206412 2.565646 3 1.431256 1.340309 -1.170299 -0.226169 4 0.410835 0.813850 0.132003 -0.827317
指定解析引擎
Pandas 目前支持三种引擎,C 引擎、Python 引擎和实验性的 pyarrow 引擎(需要pyarrow软件包)。一般来说,pyarrow 引擎在较大的工作负载上速度最快,在大多数其他工作负载上与 C 引擎的速度相当。Python 引擎在大多数工作负载上比 pyarrow 和 C 引擎慢。但是,与 C 引擎相比,pyarrow 引擎要不那么稳定,缺少一些与 Python 引擎相比的功能。
在可能的情况下,pandas 使用 C 解析器(指定为engine='c'),但如果指定了不受 C 支持的选项,则可能会退回到 Python。
目前,C 和 pyarrow 引擎不支持的选项包括:
sep不是单个字符(例如正则表达式分隔符)skipfootersep=None与delim_whitespace=False
指定上述任何选项将产生一个ParserWarning,除非显式选择engine='python'来选择 Python 引擎。
pyarrow 引擎不支持的选项,不在上面的列表中包括:
float_precisionchunksizecommentnrowsthousandsmemory_mapdialecton_bad_linesdelim_whitespacequotinglineterminatorconvertersdecimaliteratordayfirstinfer_datetime_formatverboseskipinitialspacelow_memory
使用engine='pyarrow'指定这些选项将引发ValueError。
读取/写入远程文件
您可以传递一个 URL 给许多 pandas 的 IO 函数来读取或写入远程文件 - 以下示例显示了读取 CSV 文件:
df = pd.read_csv("https://download.bls.gov/pub/time.series/cu/cu.item", sep="\t")
版本 1.3.0 中的新功能。
可以通过将头键值映射的字典传递给storage_options关键字参数来发送自定义标头,如下所示:
headers = {"User-Agent": "pandas"} df = pd.read_csv( "https://download.bls.gov/pub/time.series/cu/cu.item", sep="\t", storage_options=headers )
所有不是本地文件或 HTTP(s) 的 URL 都由fsspec处理,如果安装了它,以及其各种文件系统实现(包括 Amazon S3、Google Cloud、SSH、FTP、webHDFS…)。其中一些实现将需要安装其他软件包,例如 S3 URL 需要s3fs库:
df = pd.read_json("s3://pandas-test/adatafile.json")
当处理远程存储系统时,您可能需要在特殊位置的环境变量或配置文件中进行额外配置。例如,要访问您的 S3 存储桶中的数据,您需要在S3Fs documentation中列出的几种方式之一中定义凭据。对于几个存储后端,情况也是如此,您应该遵循fsspec内置的fsimpl1和未包含在主fsspec分发中的fsimpl2的链接。
您还可以直接将参数传递给后端驱动程序。由于fsspec不使用AWS_S3_HOST环境变量,因此我们可以直接定义一个包含 endpoint_url 的字典,并将对象传递给存储选项参数:
storage_options = {"client_kwargs": {"endpoint_url": "http://127.0.0.1:5555"}}} df = pd.read_json("s3://pandas-test/test-1", storage_options=storage_options)
更多示例配置和文档可以在S3Fs documentation中找到。
如果您没有 S3 凭据,仍然可以通过指定匿名连接来访问公共数据,例如
新版本 1.2.0 中。
pd.read_csv( "s3://ncei-wcsd-archive/data/processed/SH1305/18kHz/SaKe2013" "-D20130523-T080854_to_SaKe2013-D20130523-T085643.csv", storage_options={"anon": True}, )
fsspec还允许使用复杂的 URL,用于访问压缩存档中的数据,文件的本地缓存等。要在本地缓存上述示例,您需要修改调用方式为
pd.read_csv( "simplecache::s3://ncei-wcsd-archive/data/processed/SH1305/18kHz/" "SaKe2013-D20130523-T080854_to_SaKe2013-D20130523-T085643.csv", storage_options={"s3": {"anon": True}}, )
在这里我们指定“anon”参数是针对实现的“s3”部分,而不是缓存实现。请注意,这仅在会话期间缓存到临时目录,但您还可以指定一个永久存储。
写出数据
写入到 CSV 格式
Series和DataFrame对象具有一个实例方法to_csv,允许将对象的内容存储为逗号分隔值文件。该函数接受多个参数。只需要第一个。
path_or_buf: 要写入的文件的字符串路径或文件对象。如果是文件对象,则必须使用newline=''打开。sep: 输出文件的字段分隔符(默认为“,”)na_rep: 缺失值的字符串表示(默认为‘’)float_format: 浮点数的格式字符串columns: 写入的列(默认为 None)header: 是否写出列名(默认为 T