pandas 文档字符串指南#
关于文档字符串和标准#
Python 文档字符串是用于记录 Python 模块、类、函数或方法的字符串,以便程序员无需阅读实现细节即可了解其功能。
此外,从文档字符串自动生成在线(html)文档是一种常见做法。 Sphinx 实现了这一目的。
以下示例展示了文档字符串的示例。
def add(num1, num2):
"""
Add up two integer numbers.
This function simply wraps the ``+`` operator, and does not
do anything interesting, except for illustrating what
the docstring of a very simple function looks like.
Parameters
----------
num1 : int
First number to add.
num2 : int
Second number to add.
Returns
-------
int
The sum of ``num1`` and ``num2``.
See Also
--------
subtract : Subtract one integer from another.
Examples
--------
>>> add(2, 2)
4
>>> add(25, 0)
25
>>> add(10, -10)
0
"""
return num1 + num2
关于文档字符串存在一些标准,这些标准使它们更易于阅读,并允许它们轻松导出到其他格式,例如 html 或 pdf。
每个 Python 文档字符串应遵循的首要约定在 PEP-257 中定义。
由于 PEP-257 范围很广,因此还存在其他更具体的标准。在 pandas 的情况下,遵循 NumPy 文档字符串约定。这些约定将在本文档中说明。
numpydoc 是一个 Sphinx 扩展,用于支持 NumPy 文档字符串约定。
该标准使用 reStructuredText (reST)。reStructuredText 是一种标记语言,允许在纯文本文件中编码样式。有关 reStructuredText 的文档可以在以下位置找到
pandas 有一些帮助程序用于在相关类之间共享文档字符串,请参见 共享文档字符串。
本文档的其余部分将总结所有上述指南,并将提供特定于 pandas 项目的其他约定。
编写文档字符串#
一般规则#
文档字符串必须用三个双引号定义。在文档字符串之前或之后不应留空行。文本从开头的引号后的下一行开始。结束引号有自己的行(意味着它们不在最后一句话的末尾)。
在极少数情况下,reST 样式(如粗体文本或斜体)将用于文档字符串,但使用内联代码很常见,它在反引号之间呈现。以下被认为是内联代码
参数的名称
Python 代码、模块、函数、内置函数、类型、文字……(例如
os
、list
、numpy.abs
、datetime.date
、True
)pandas 类(以
:class:`pandas.Series`
的形式)pandas 方法(以
:meth:`pandas.Series.sum`
的形式)pandas 函数(以
:func:`pandas.to_datetime`
的形式)
注意
要仅显示链接的类、方法或函数的最后一个组件,请在其前面加上 ~
。例如,:class:`~pandas.Series`
将链接到 pandas.Series
,但仅显示最后部分 Series
作为链接文本。有关详细信息,请参见 Sphinx 交叉引用语法。
好的
def add_values(arr):
"""
Add the values in ``arr``.
This is equivalent to Python ``sum`` of :meth:`pandas.Series.sum`.
Some sections are omitted here for simplicity.
"""
return sum(arr)
不好的
def func():
"""Some function.
With several mistakes in the docstring.
It has a blank like after the signature ``def func():``.
The text 'Some function' should go in the line after the
opening quotes of the docstring, not in the same line.
There is a blank line between the docstring and the first line
of code ``foo = 1``.
The closing quotes should be in the next line, not in this one."""
foo = 1
bar = 2
return foo + bar
第 1 节:简短摘要#
简短摘要是一个句子,以简洁的方式表达函数的作用。
简短摘要必须以大写字母开头,以句号结尾,并适合一行。它需要表达对象的作用,而不提供细节。对于函数和方法,简短摘要必须以不定式动词开头。
好的
def astype(dtype):
"""
Cast Series type.
This section will provide further details.
"""
pass
不好的
def astype(dtype):
"""
Casts Series type.
Verb in third-person of the present simple, should be infinitive.
"""
pass
def astype(dtype):
"""
Method to cast Series type.
Does not start with verb.
"""
pass
def astype(dtype):
"""
Cast Series type
Missing dot at the end.
"""
pass
def astype(dtype):
"""
Cast Series type from its current type to the new type defined in
the parameter dtype.
Summary is too verbose and doesn't fit in a single line.
"""
pass
第二部分:扩展摘要#
扩展摘要提供有关函数功能的详细信息。它不应详细介绍参数,也不应讨论实现说明,这些内容将在其他部分中介绍。
在简短摘要和扩展摘要之间留有一行空白。扩展摘要中的每个段落都以句号结尾。
扩展摘要应提供有关函数用途及其用例的详细信息,前提是它不是过于通用的。
def unstack():
"""
Pivot a row index to columns.
When using a MultiIndex, a level can be pivoted so each value in
the index becomes a column. This is especially useful when a subindex
is repeated for the main index, and data is easier to visualize as a
pivot table.
The index level will be automatically removed from the index when added
as columns.
"""
pass
第三部分:参数#
参数的详细信息将在此部分添加。本部分标题为“参数”,后面是一行,每个字母下面都有一个连字符。在部分标题之前留有一行空白,但在标题之后和“参数”行与连字符行之间没有空白。
在标题之后,必须记录签名中的每个参数,包括 *args
和 **kwargs
,但不包括 self
。
参数由其名称、空格、冒号、另一个空格和类型(或类型)定义。请注意,名称和冒号之间的空格很重要。类型未为 *args
和 **kwargs
定义,但必须为所有其他参数定义。在参数定义之后,必须有一行参数描述,该描述缩进,并且可以包含多行。描述必须以大写字母开头,并以句号结尾。
对于具有默认值的关键字参数,默认值将在类型的末尾以逗号分隔列出。在这种情况下,类型的确切形式将为“int,默认值 0”。在某些情况下,解释默认参数的含义可能很有用,这可以在逗号之后添加“int,默认值 -1,表示所有 cpu”。
在默认值为 None
的情况下,表示该值不会被使用。建议使用 "str, optional"
而不是 "str, default None"
。当 None
是一个正在使用的值时,我们将保留“str, default None”的形式。例如,在 df.to_csv(compression=None)
中,None
不是一个正在使用的值,而是表示压缩是可选的,如果没有提供则不进行压缩。在这种情况下,我们将使用 "str, optional"
。只有在像 func(value=None)
这样的情况下,None
与 0
或 foo
的使用方式相同,我们将指定“str, int or None, default None”。
好的
class Series:
def plot(self, kind, color='blue', **kwargs):
"""
Generate a plot.
Render the data in the Series as a matplotlib plot of the
specified kind.
Parameters
----------
kind : str
Kind of matplotlib plot.
color : str, default 'blue'
Color name or rgb code.
**kwargs
These parameters will be passed to the matplotlib plotting
function.
"""
pass
不好的
class Series:
def plot(self, kind, **kwargs):
"""
Generate a plot.
Render the data in the Series as a matplotlib plot of the
specified kind.
Note the blank line between the parameters title and the first
parameter. Also, note that after the name of the parameter ``kind``
and before the colon, a space is missing.
Also, note that the parameter descriptions do not start with a
capital letter, and do not finish with a dot.
Finally, the ``**kwargs`` parameter is missing.
Parameters
----------
kind: str
kind of matplotlib plot
"""
pass
参数类型#
在指定参数类型时,可以直接使用 Python 内置数据类型(优先使用 Python 类型,而不是更详细的字符串、整数、布尔值等)。
int
float
str
bool
对于复杂类型,定义子类型。对于 dict
和 tuple
,由于存在多种类型,我们使用括号来帮助阅读类型(dict
使用花括号,tuple
使用普通括号)。
list of int
dict of {str : int}
tuple of (str, int, int)
tuple of (str,)
set of str
如果只允许一组值,请将它们列在花括号中,并用逗号(后跟空格)分隔。如果这些值是有序的并且有顺序,请按此顺序列出它们。否则,如果存在默认值,请先列出默认值。
{0, 10, 25}
{‘simple’, ‘advanced’}
{‘low’, ‘medium’, ‘high’}
{‘cat’, ‘dog’, ‘bird’}
如果类型在 Python 模块中定义,则必须指定模块。
datetime.date
datetime.datetime
decimal.Decimal
如果类型在包中,则也必须指定模块。
numpy.ndarray
scipy.sparse.coo_matrix
如果类型是 pandas 类型,除了 Series 和 DataFrame 之外,还需要指定 pandas。
Series
DataFrame
pandas.Index
pandas.Categorical
pandas.arrays.SparseArray
如果确切类型不相关,但必须与 NumPy 数组兼容,则可以指定 array-like。如果接受任何可以迭代的类型,则可以使用 iterable。
array-like
iterable
如果接受多种类型,请用逗号分隔它们,除了最后两种类型,它们需要用“或”一词分隔。
int 或 float
float, decimal.Decimal 或 None
str 或 str 列表
如果 None
是接受的值之一,它始终需要是列表中的最后一个。
对于轴,惯例是使用类似以下内容:
axis : {0 或 ‘index’, 1 或 ‘columns’, None}, 默认 None
第 4 节:返回或生成#
如果方法返回值,它将在本节中记录。如果方法生成其输出,也是如此。
本节的标题将与“参数”的定义方式相同。使用“返回”或“生成”的名称,后跟一行与前一个单词的字母数量相同的连字符。
返回值的文档与参数类似。但在这种情况下,不会提供名称,除非方法返回或生成多个值(值的元组)。
“返回”和“生成”的类型与“参数”的类型相同。此外,描述必须以句号结尾。
例如,使用单个值
def sample():
"""
Generate and return a random number.
The value is sampled from a continuous uniform distribution between
0 and 1.
Returns
-------
float
Random number generated.
"""
return np.random.random()
使用多个值
import string
def random_letters():
"""
Generate and return a sequence of random letters.
The length of the returned string is also random, and is also
returned.
Returns
-------
length : int
Length of the returned string.
letters : str
String of random letters.
"""
length = np.random.randint(1, 10)
letters = ''.join(np.random.choice(string.ascii_lowercase)
for i in range(length))
return length, letters
如果方法生成其值
def sample_values():
"""
Generate an infinite sequence of random numbers.
The values are sampled from a continuous uniform distribution between
0 and 1.
Yields
------
float
Random number generated.
"""
while True:
yield np.random.random()
第 5 节:另请参见#
本节用于告知用户有关 pandas 功能的信息,这些功能与正在记录的功能相关。在极少数情况下,如果根本找不到任何相关方法或函数,则可以跳过本节。
一个明显的例子是 head()
和 tail()
方法。由于 tail()
执行与 head()
相同的操作,但位于 Series
或 DataFrame
的末尾而不是开头,因此最好让用户了解这一点。
为了直观地了解哪些可以被认为是相关的,这里有一些例子
loc
和iloc
,因为它们执行相同的操作,但一种提供索引,另一种提供位置max
和min
,因为它们执行相反的操作iterrows
、itertuples
和items
,因为用户很容易在寻找迭代列的方法时最终找到迭代行的方法,反之亦然fillna
和dropna
,因为这两种方法都用于处理缺失值read_csv
和to_csv
,因为它们是互补的merge
和join
,因为一个是另一个的泛化astype
和pandas.to_datetime
,因为用户可能正在阅读astype
的文档以了解如何转换为日期,而执行此操作的方法是使用pandas.to_datetime
where
与numpy.where
相关,因为它的功能基于它。
在决定什么相关时,你应该主要使用你的常识,并思考什么对阅读文档的用户有用,特别是那些经验不足的用户。
当与其他库(主要是 numpy
)相关联时,首先使用模块的名称(而不是像 np
这样的别名)。如果函数位于不是主模块的模块中,例如 scipy.sparse
,列出完整的模块(例如 scipy.sparse.coo_matrix
)。
本节有一个标题,“另请参阅”(注意大写字母 S 和 A),后面是带连字符的行,前面是空行。
在标题之后,我们将为每个相关的函数或方法添加一行,后面是空格、冒号、另一个空格,以及一个简短的描述,说明该函数或方法的作用、它在该上下文中为什么相关,以及所记录的函数与被引用的函数之间的关键区别。描述也必须以句号结尾。
请注意,在“返回值”和“生成”中,描述位于类型后面的行上。然而,在本节中,它位于同一行上,中间有一个冒号。如果描述不适合同一行,它可以继续到其他行,这些行必须进一步缩进。
例如
class Series:
def head(self):
"""
Return the first 5 elements of the Series.
This function is mainly useful to preview the values of the
Series without displaying the whole of it.
Returns
-------
Series
Subset of the original series with the 5 first values.
See Also
--------
Series.tail : Return the last 5 elements of the Series.
Series.iloc : Return a slice of the elements in the Series,
which can also be used to return the first or last n.
"""
return self.iloc[:5]
第 6 节:注释#
这是一个可选部分,用于记录算法实现的注释,或记录函数行为的技术方面。
随意跳过它,除非你熟悉算法的实现,或者你在为函数编写示例时发现了一些违反直觉的行为。
本节遵循与扩展摘要部分相同的格式。
第 7 节:示例#
尽管放在最后的位置,但这仍然是文档字符串中最重要的部分之一,因为人们通常通过示例而不是准确的解释来更好地理解概念。
文档字符串中的示例,除了说明函数或方法的使用外,还必须是有效的 Python 代码,以确定性的方式返回给定的输出,并且用户可以复制和运行。
示例以 Python 终端会话的形式呈现。 >>>
用于表示代码。 ...
用于表示从前一行继续的代码。输出在生成输出的最后一行代码之后立即呈现(中间没有空行)。描述示例的注释可以在前后添加空行。
示例的呈现方式如下
导入所需的库(除了
numpy
和pandas
)创建示例所需的數據
展示一个非常基本的示例,它可以提供对最常见用例的了解
添加带有解释的示例,说明如何使用参数来实现扩展功能
一个简单的示例可能是
class Series:
def head(self, n=5):
"""
Return the first elements of the Series.
This function is mainly useful to preview the values of the
Series without displaying all of it.
Parameters
----------
n : int
Number of values to return.
Return
------
pandas.Series
Subset of the original series with the n first values.
See Also
--------
tail : Return the last n elements of the Series.
Examples
--------
>>> ser = pd.Series(['Ant', 'Bear', 'Cow', 'Dog', 'Falcon',
... 'Lion', 'Monkey', 'Rabbit', 'Zebra'])
>>> ser.head()
0 Ant
1 Bear
2 Cow
3 Dog
4 Falcon
dtype: object
With the ``n`` parameter, we can change the number of returned rows:
>>> ser.head(n=3)
0 Ant
1 Bear
2 Cow
dtype: object
"""
return self.iloc[:n]
示例应尽可能简洁。在函数的复杂性需要较长示例的情况下,建议使用带有粗体标题的块。使用双星号 **
使文本变为粗体,例如在 **this** example**
中。
示例的约定#
示例中的代码假定始终以这两行开头,这两行不会显示
import numpy as np
import pandas as pd
示例中使用的任何其他模块都必须显式导入,每行一个(如 PEP 8#imports 中推荐的那样),并避免使用别名。避免过度导入,但如果需要,标准库中的导入应放在首位,然后是第三方库(如 matplotlib)。
当使用单个 Series
说明示例时,使用名称 ser
,如果使用单个 DataFrame
,则使用名称 df
。对于索引,idx
是首选名称。如果使用一组同构的 Series
或 DataFrame
,则分别将其命名为 ser1
、ser2
、ser3
… 或 df1
、df2
、df3
… 如果数据不是同构的,并且需要多个结构,则使用有意义的名称来命名它们,例如 df_main
和 df_to_join
。
示例中使用的数据应尽可能简洁。建议行数约为 4 行,但要根据具体示例选择合适的行数。例如,在 head
方法中,需要大于 5 行才能显示默认值的示例。如果进行 mean
操作,可以使用类似 [1, 2, 3]
的数据,这样很容易看出返回的值是平均值。
对于更复杂的示例(例如分组),避免使用没有解释的数据,例如带有 A、B、C、D 等列的随机数矩阵。相反,使用有意义的示例,这将更容易理解概念。除非示例需要,否则使用动物名称,以保持示例一致。并使用它们的数值属性。
调用方法时,首选关键字参数 head(n=3)
,而不是位置参数 head(3)
。
好的
class Series:
def mean(self):
"""
Compute the mean of the input.
Examples
--------
>>> ser = pd.Series([1, 2, 3])
>>> ser.mean()
2
"""
pass
def fillna(self, value):
"""
Replace missing values by ``value``.
Examples
--------
>>> ser = pd.Series([1, np.nan, 3])
>>> ser.fillna(0)
[1, 0, 3]
"""
pass
def groupby_mean(self):
"""
Group by index and return mean.
Examples
--------
>>> ser = pd.Series([380., 370., 24., 26],
... name='max_speed',
... index=['falcon', 'falcon', 'parrot', 'parrot'])
>>> ser.groupby_mean()
index
falcon 375.0
parrot 25.0
Name: max_speed, dtype: float64
"""
pass
def contains(self, pattern, case_sensitive=True, na=numpy.nan):
"""
Return whether each value contains ``pattern``.
In this case, we are illustrating how to use sections, even
if the example is simple enough and does not require them.
Examples
--------
>>> ser = pd.Series('Antelope', 'Lion', 'Zebra', np.nan)
>>> ser.contains(pattern='a')
0 False
1 False
2 True
3 NaN
dtype: bool
**Case sensitivity**
With ``case_sensitive`` set to ``False`` we can match ``a`` with both
``a`` and ``A``:
>>> s.contains(pattern='a', case_sensitive=False)
0 True
1 False
2 True
3 NaN
dtype: bool
**Missing values**
We can fill missing values in the output using the ``na`` parameter:
>>> ser.contains(pattern='a', na=False)
0 False
1 False
2 True
3 False
dtype: bool
"""
pass
不好的
def method(foo=None, bar=None):
"""
A sample DataFrame method.
Do not import NumPy and pandas.
Try to use meaningful data, when it makes the example easier
to understand.
Try to avoid positional arguments like in ``df.method(1)``. They
can be all right if previously defined with a meaningful name,
like in ``present_value(interest_rate)``, but avoid them otherwise.
When presenting the behavior with different parameters, do not place
all the calls one next to the other. Instead, add a short sentence
explaining what the example shows.
Examples
--------
>>> import numpy as np
>>> import pandas as pd
>>> df = pd.DataFrame(np.random.randn(3, 3),
... columns=('a', 'b', 'c'))
>>> df.method(1)
21
>>> df.method(bar=14)
123
"""
pass
让示例通过 doctests 的技巧#
让示例在验证脚本中通过 doctests 有时会很棘手。以下是一些需要注意的地方
导入所有需要的库(除了 pandas 和 NumPy,它们已经作为
import pandas as pd
和import numpy as np
导入),并定义示例中使用的所有变量。尽量避免使用随机数据。但是,在某些情况下,随机数据可能是可以的,例如,如果您正在记录的函数处理概率分布,或者使函数结果有意义所需的数据量太大,以至于手动创建它非常麻烦。在这些情况下,始终使用固定的随机种子来使生成的示例可预测。示例
>>> np.random.seed(42) >>> df = pd.DataFrame({'normal': np.random.normal(100, 5, 20)})
如果您有一个跨越多行的代码片段,您需要在续行上使用 '...'
>>> df = pd.DataFrame([[1, 2, 3], [4, 5, 6]], index=['a', 'b', 'c'], ... columns=['A', 'B'])
如果您想显示一个引发异常的情况,您可以这样做
>>> pd.to_datetime(["712-01-01"]) Traceback (most recent call last): OutOfBoundsDatetime: Out of bounds nanosecond timestamp: 712-01-01 00:00:00
包含“Traceback (most recent call last):” 是必不可少的,但对于实际错误,仅错误名称就足够了。
如果结果中有一小部分可能会有所不同(例如,对象表示中的哈希),您可以使用
...
来表示这部分。如果你想证明
s.plot()
返回一个 matplotlib AxesSubplot 对象,这将导致 doctest 失败。>>> s.plot() <matplotlib.axes._subplots.AxesSubplot at 0x7efd0c0b0690>
但是,你可以这样做(注意需要添加的注释)
>>> s.plot() <matplotlib.axes._subplots.AxesSubplot at ...>
示例中的绘图#
pandas 中有一些方法返回绘图。为了渲染文档中示例生成的绘图,存在 .. plot::
指令。
要使用它,请将下一段代码放在“示例”标题之后,如下所示。在构建文档时,绘图将自动生成。
class Series:
def plot(self):
"""
Generate a plot with the ``Series`` data.
Examples
--------
.. plot::
:context: close-figs
>>> ser = pd.Series([1, 2, 3])
>>> ser.plot()
"""
pass