带有熊猫的 Python 类型提示?

Posted

技术标签:

【中文标题】带有熊猫的 Python 类型提示?【英文标题】:Pythonic type hints with pandas? 【发布时间】:2017-10-09 00:08:32 【问题描述】:

让我们看一个简单的函数,它接受一个 str 并返回一个数据帧:

import pandas as pd
def csv_to_df(path):
    return pd.read_csv(path, skiprows=1, sep='\t', comment='#')

向该函数添加类型提示的推荐 Python 方法是什么?

如果我向 python 询问 DataFrame 的类型,它会返回 pandas.core.frame.DataFrame。 以下内容不起作用,因为它会告诉我 pandas 未定义。

 def csv_to_df(path: str) -> pandas.core.frame.DataFrame:
     return pd.read_csv(path, skiprows=1, sep='\t', comment='#')

【问题讨论】:

但是您使用的是pd 别名,您可能可以定义自定义类型。 @MosesKoledoye 如果我尝试 pd.core.frame.DataFrame 我会得到一个AttributeError 而不是NameError 我不是“pythonicity”的权威,但我会推荐 doc-strings(使用 ''' this function takes a inputType and returns an outputType ''')如果有人在你的函数上调用 help(yourFunction) 函数,这也是将显示的内容。跨度> dataenforce允许检查数据框github.com/CedricFR/dataenforce中的数据类型 【参考方案1】:

为什么不直接使用pd.DataFrame

import pandas as pd
def csv_to_df(path: str) -> pd.DataFrame:
    return pd.read_csv(path, skiprows=1, sep='\t', comment='#')

结果是一样的:

> help(csv_to_df)
Help on function csv_to_df in module __main__:
csv_to_df(path:str) -> pandas.core.frame.DataFrame

【讨论】:

注意:这假定您 import pandas as pd 在脚本的顶部。仅导入 main 是不够的,因为 pd 无法解析。 它也不允许为特定列指定 dtypes,这可能非常有用 @Philipp_Kats 目前没有办法在类型提示中为 DataFrame 列指定 dtypes,I haven't seen 在这个方向上完成的任何工作(如果我错了,请纠正我)。将有关类型提示的相关问题与 NumPy 和 dtypes 联系起来:Type hint for NumPy ndarray dtype?。你会看到它也是not implemented there yet。 这会在 mypy error: No library stub file for module 'pandas' 中出现错误 @user2304916 见Unable to suppress No library stub file for module... error。【参考方案2】:

我目前正在做以下事情:

from typing import TypeVar
PandasDataFrame = TypeVar('pandas.core.frame.DataFrame')
def csv_to_df(path: str) -> PandasDataFrame:
    return pd.read_csv(path, skiprows=1, sep='\t', comment='#')

这给出了:

> help(csv_to_df)
Help on function csv_to_df in module __main__:

csv_to_df(path:str) -> ~pandas.core.frame.DataFrame

不知道那是多么pythonic,但我发现它作为一种类型提示是可以理解的。

【讨论】:

@Azat Ibrakov 您介意详细说明您的评论吗?有时我不确定什么是“pythonic”,什么不是“pythonic”。 我看到人们不赞成这个答案。就上下文而言,这是我为自己的问题找到的解决方案,并且就所有意图和目的而言,它都可以正常工作。上面更 Pythonic 的解决方案,我接受为正确答案(但确实有自己的好处,请参阅 cmets),仅在 8 个月后提供。 这不是pythonic,因为它比这个问题的公认答案更清晰且更难维护。由于此处的类型路径未经过编译器验证,因此如果错误不会引发错误。这可能是由于您的 TypeVar arg 中的拼写错误或更改为模块本身造成的。 我在使用这个时收到警告:The argument to 'TypeVar()' must be a string equal to the variable name to which it is assigned @Azat Ibrakov 这些“pythonic”和“not pythonic”的论点就像许多“Pythonists”的口头禅。我认为我们应该停止这种风格的争论。 A 从未听过这种类型的论据,例如Java 开发人员。在我看来,这个解决方案没有任何问题。【参考方案3】:

现在有一个 pip 包可以帮助解决这个问题。 https://github.com/CedricFR/dataenforce

您可以使用 pip install dataenforce 安装它并使用非常 Python 的类型提示,例如:

def preprocess(dataset: Dataset["id", "name", "location"]) -> Dataset["location", "count"]:
    pass

【讨论】:

【参考方案4】:

这偏离了原始问题,但使用TypeVar 和@Georgy 的评论构建了@dangom 的答案,即无法在类型提示中为DataFrame 列指定数据类型,您可以使用这样的简单解决方法在 DataFrame 中指定数据类型:

from typing import TypeVar
DataFrameStr = TypeVar("pandas.core.frame.DataFrame(str)")
def csv_to_df(path: str) -> DataFrameStr:
    return pd.read_csv(path, skiprows=1, sep='\t', comment='#')

【讨论】:

【参考方案5】:

查看here 给出的答案,其中解释了包data-science-types 的用法。

pip install data-science-types

演示

# program.py

import pandas as pd

df: pd.DataFrame = pd.DataFrame('col1': [1,2,3], 'col2': [4,5,6]) # OK
df1: pd.DataFrame = pd.Series([1,2,3]) # error: Incompatible types in assignment

以同样的方式使用 mypy 运行:

$ mypy program.py

【讨论】:

不幸的是,这被埋在了底部。 这是 2021 年的最佳答案。 请注意 Daniel Malachov 在链接答案 (***.com/a/63446142/8419574) 之后发表的评论。 @user3897315 - 我不同意这是 2021 年的最佳答案。如果您访问 data-science-types on GitHub,您会发现存储库已存档,并且自述文件已更新(2021 年 2 月 16 日)以下注释:“⚠️ 这个项目大部分已经停止开发 ⚠️ pandas 团队和 numpy 团队都在将类型存根集成到他们的代码库中,我们没有看到与之竞争的意义他们。” 我同意,但之后我看不到 pandas 或 numpy 将在其路线图中推送这些或 ETA 的时间表。

以上是关于带有熊猫的 Python 类型提示?的主要内容,如果未能解决你的问题,请参考以下文章

带有异常的 Python 类型提示

带有存根的子类的 Python 2.7 类型提示

如何输入多索引熊猫数据框 Python3.8+ 的提示?

是否有带有可选类型提示的 OOP 语言?

在 PyCharm 中隐藏 Python 类型提示

phpstorm 生成带有类型提示的设置器