Pythonic类型的提示与熊猫?

dan*_*gom 28 python typing

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

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

为此函数添加类型提示的推荐pythonic方法是什么?

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

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

Geo*_*rgy 43

为什么不用pd.DataFrame

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

结果是一样的:

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

  • 它也不允许为特定列指定数据类型,这可能非常有用 (9认同)
  • @Philipp_Kats 目前无法在类型提示中为 DataFrame 列指定 dtypes,并且[我还没有看到](https://github.com/pandas-dev/pandas/issues/25601)在这个方向上完成的任何工作(如我错了请纠正我)。将有关类型提示的相关问题与 NumPy 和 dtypes 链接起来:[*NumPy ndarray dtype 的类型提示?*](/sf/ask/3815277511/)。您会看到它[尚未在那里实现](https://github.com/numpy/numpy-stubs/issues/7)。 (5认同)
  • 注意:假设您在脚本顶部将pandas作为pd导入。仅导入`main`是不够的,因为pd无法解析。 (4认同)
  • 这会在 mypy 中出现错误“错误:没有模块‘pandas’的库存根文件” (2认同)

dan*_*gom 11

我目前正在做以下事情:

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='#')
Run Code Online (Sandbox Code Playgroud)

这使:

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

csv_to_df(path:str) -> ~pandas.core.frame.DataFrame
Run Code Online (Sandbox Code Playgroud)

不知道pythonic是怎么回事,但我发现它可以理解为类型提示.

  • 您会介意@Azat Ibrakov吗?有时我不确定什么是“ pythonic”,什么不是“ pythonic”。 (13认同)
  • 我看到人们对这个答案投了反对票。对于上下文,这是我为自己的问题找到的解决方案,并且出于所有意图和目的,它工作得很好。上面的更Pythonic的解决方案,我接受它作为正确答案(但确实有它自己的好处,请参阅评论),仅在8个月后提供。 (5认同)
  • 它不是 pythonic,因为它比这个问题的公认答案不太清晰且更难维护。由于此处的类型路径未经编译器验证,因此如果错误也不会引发错误。这可能是由于“TypeVar”参数中的拼写错误或模块本身的更改造成的。 (5认同)
  • 这不是类型变量的正确用法。`TypeVar` 的存在将两种类型链接在一起([mypy docs](https://mypy.readthedocs.io/en/stable/generics.html))。您可能指的是类型_别名_:`PandasDataFrame = pandas.core.frame.DataFrame` (5认同)
  • 当我使用它时,我收到一条警告:“‘TypeVar()’的参数必须是一个等于为其分配的变量名称的字符串” (4认同)
  • 这根本不是pythonic (3认同)

luk*_*ris 10

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

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

def preprocess(dataset: Dataset["id", "name", "location"]) -> Dataset["location", "count"]:
    pass
Run Code Online (Sandbox Code Playgroud)


dvb*_*dvb 10

看看潘德拉

pandera 提供了灵活且富有表现力的 API,用于对类似数据框的对象执行数据验证,从而使数据处理管道更具可读性和健壮性。数据帧包含 pandera 在运行时显式验证的信息。这在生产关键或可重复的研究环境中非常有用。


pandera 的优点是您还可以指定各个 DataFrame 列的数据类型。以下示例使用 pandera 来运行时强制包含单列整数的 DataFrame:

import pandas as pd
import pandera
from pandera.typing import DataFrame, Series

class Integers(pandera.SchemaModel):
    number: Series[int] 

@pandera.check_types
def my_fn(a: DataFrame[Integers]) -> None:
    pass

# This works
df = pd.DataFrame({"number": [ 2002, 2003]})
my_fn(df)

# Raises an exception
df = pd.DataFrame({"number": [ 2002.0, 2003]})
my_fn(df)

# Raises an exception
df = pd.DataFrame({"number": [ '2002', 2003]})
my_fn(df)
Run Code Online (Sandbox Code Playgroud)


kev*_*und 7

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

pip install data-science-types
Run Code Online (Sandbox Code Playgroud)

演示

# 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
Run Code Online (Sandbox Code Playgroud)

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

$ mypy program.py

  • @user3897315 - 我不同意这是 2021 年的最佳答案。如果您访问 [GitHub 上的 data-science-types](https://github.com/predictive-analytics-lab/data-science-types),您会找到存储库已存档,并且自述文件已更新(2021 年 2 月 16 日),其中包含以下注释:“⚠️ **此项目已基本停止开发** ⚠️ pandas 团队和 numpy 团队都在集成类型的过程中存根到他们的代码库中,我们看不到与他们竞争的意义。” (7认同)