Pandas 2.2 中文官方教程和指南(十·二)(4)

简介: Pandas 2.2 中文官方教程和指南(十·二)

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]) 

在上面的例子中,55.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"]) 

上面,NA0 都作为字符串是 NaN

pd.read_csv("path_to_file.csv", na_values=["Nope"]) 

默认值除了字符串 "Nope" 外,也被识别为 NaN。 ### 无穷大

类似 inf 的值将被解析为 np.inf(正无穷大),而 -inf 将被解析为 -np.inf(负无穷大)。这些将忽略值的大小写,意味着 Inf 也将被解析为 np.inf。 ### 布尔值

常见的值 TrueFalseTRUEFALSE 都被识别为布尔值。偶尔你可能想要识别其他值为布尔值。为此,请使用如下所示的 true_valuesfalse_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_csvindex_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 不是单个字符(例如正则表达式分隔符)
  • skipfooter
  • sep=Nonedelim_whitespace=False

指定上述任何选项将产生一个ParserWarning,除非显式选择engine='python'来选择 Python 引擎。

pyarrow 引擎不支持的选项,不在上面的列表中包括:

  • float_precision
  • chunksize
  • comment
  • nrows
  • thousands
  • memory_map
  • dialect
  • on_bad_lines
  • delim_whitespace
  • quoting
  • lineterminator
  • converters
  • decimal
  • iterator
  • dayfirst
  • infer_datetime_format
  • verbose
  • skipinitialspace
  • low_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 格式

SeriesDataFrame对象具有一个实例方法to_csv,允许将对象的内容存储为逗号分隔值文件。该函数接受多个参数。只需要第一个。

  • path_or_buf: 要写入的文件的字符串路径或文件对象。如果是文件对象,则必须使用newline=''打开。
  • sep: 输出文件的字段分隔符(默认为“,”)
  • na_rep: 缺失值的字符串表示(默认为‘’)
  • float_format: 浮点数的格式字符串
  • columns: 写入的列(默认为 None)
  • header: 是否写出列名(默认为 T
相关文章
|
SQL 数据采集 数据挖掘
Pandas 教程
10月更文挑战第25天
316 2
|
数据采集 存储 数据可视化
Pandas高级教程:数据清洗、转换与分析
Pandas是Python的数据分析库,提供Series和DataFrame数据结构及数据分析工具,便于数据清洗、转换和分析。本教程涵盖Pandas在数据清洗(如缺失值、重复值和异常值处理)、转换(数据类型转换和重塑)和分析(如描述性统计、分组聚合和可视化)的应用。通过学习Pandas,用户能更高效地处理和理解数据,为数据分析任务打下基础。
1558 3
|
存储 JSON 数据格式
Pandas 使用教程 CSV - CSV 转 JSON
Pandas 使用教程 CSV - CSV 转 JSON
224 0
|
JSON 数据格式 Python
Pandas 使用教程 JSON
Pandas 使用教程 JSON
306 0
|
SQL 数据采集 JSON
Pandas 使用教程 Series、DataFrame
Pandas 使用教程 Series、DataFrame
406 0
|
索引 Python
Pandas 2.2 中文官方教程和指南(一)(4)
Pandas 2.2 中文官方教程和指南(一)
255 0
|
存储 SQL JSON
Pandas 2.2 中文官方教程和指南(一)(3)
Pandas 2.2 中文官方教程和指南(一)
307 0
|
XML 关系型数据库 PostgreSQL
Pandas 2.2 中文官方教程和指南(一)(2)
Pandas 2.2 中文官方教程和指南(一)
606 0
|
XML 关系型数据库 MySQL
Pandas 2.2 中文官方教程和指南(一)(1)
Pandas 2.2 中文官方教程和指南(一)
1168 0
|
C++ 索引 Python
Pandas 2.2 中文官方教程和指南(五)(4)
Pandas 2.2 中文官方教程和指南(五)
194 0

热门文章

最新文章