带有熊猫的 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 类型提示?的主要内容,如果未能解决你的问题,请参考以下文章