Dask 设置列 astype 对我不起作用
Dask set column astype not working for me
我无法将 Dask 列转换为特定数据类型。为了简单起见,我将提供单个列 PehRecID - 一列浮点数的详细信息。我已确认所有值都是数字。
以下是我尝试过的内容的总结:
设置数据帧数据类型。我通过了一个 dict 并得到了我预期的结果。当我做 print(df.dtypes)
我得到 {'PehRecID': 'float64', 'PehAccrualCode': 'object', ....
所以我已经成功地设置了数据类型。
使用以下代码将列显式转换为 float64:
df['PehRecID'] = df['PehRecID'].astype('float64')
当我尝试 df.to_parquet('foo.parquet', engine='pyarrow')
我得到 ValueError: could not convert string to float: 'PehRecID'
当我尝试 print(df.head())
我也 get ValueError: could not convert string to float: 'PehRecID'
看来问题出在 Dask,而不是 Parquet。
我正在处理的文件有时对于 Pandas 来说太大了,但并不大。在这种情况下,我实际上是在尝试使用一个相当小的文件来获得正确的基础知识。
使用 dask 时,了解 dask evaluates tasks lazily and asynchronously 很重要,这意味着当您输入命令时,dash 会安排 但不会执行命令 直到需要(因为 write
、compute
、print
、head
或其他命令需要为该步骤计算结果)。这意味着错误可能会作为一个步骤的结果发生,但您可能要等到稍后执行几个命令后才会发现错误,然后再恢复可能为时已晚。
在您的情况下,df['PehRecID'] = df['PehRecID'].astype('float64')
似乎是罪魁祸首。您在稍后的步骤中收到错误 ValueError: could not convert string to float: 'PehRecID'
,例如 df.head()
,因为您已将带有错误 的命令 的结果分配给数据帧列,使该列不可用。
作为一个非常简单的例子,让我们创建一个包含四个字符串值的 dask 数据帧,其中前三个可以转换为 int,最后一个不能:
In [4]: df = ddf.from_pandas(
...: pd.DataFrame({'A': ['1', '2', '3', 'not a value']}),
...: npartitions=2,
...: )
...:
In [5]: df
Out[5]:
Dask DataFrame Structure:
A
npartitions=2
0 object
2 ...
3 ...
Dask Name: from_pandas, 2 tasks
请注意,调用 df.astype(int)
不会引发错误 - 这是因为您只安排了操作 - 您还没有实际执行它:
In [6]: df.astype(int)
Out[6]:
Dask DataFrame Structure:
A
npartitions=2
0 int64
2 ...
3 ...
Dask Name: astype, 4 tasks
请注意,dtypes 现在显示 int64
,因为这是 .astype(int)
操作的结果指示的数据类型。
计算结果确实引发了预期的错误:
In [7]: df.astype(int).compute()
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-7-05b64497024c> in <module>
----> 1 df.astype(int).compute()
...
ValueError: invalid literal for int() with base 10: 'not a value'
如果就地分配结果,您可能 运行 遇到麻烦:
In [8]: df['A'] = df['A'].astype(int)
同样,数据框的 dtype 已更改以反映 .astype(int)
的预期输出:
In [9]: df.dtypes
Out[9]:
A int64
dtype: object
效果是现在无法计算df:
In [10]: df.compute()
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-14-9bb416d45ef6> in <module>
----> 1 df.compute()
...
ValueError: invalid literal for int() with base 10: 'not a value'
请注意,如果请求的分区中没有发生错误,则可以屏蔽此问题。在我的例子中,错误发生在第二个分区,所以只使用第一个分区的df.head()
,只触发第一个分区的astype(int)
操作,不报错:
In [11]: df.head()
/Users/delgadom/miniconda3/envs/rhodium-env/lib/python3.9/site-packages/dask/dataframe/core.py:6383: UserWarning: Insufficient elements for `head`. 5 elements requested, only 2 elements available. Try passing larger `npartitions` to `head`.
warnings.warn(msg.format(n, len(r)))
Out[11]:
A
0 1
1 2
如果不完全废弃列或数据帧并重新读取数据,这可能无法从中恢复,因为您已经用未来可靠地生成错误重写了列 A 的内容。
所以我认为您的特定问题的答案是您的数据不干净 - 您的列中某处确实有字符串。
我无法将 Dask 列转换为特定数据类型。为了简单起见,我将提供单个列 PehRecID - 一列浮点数的详细信息。我已确认所有值都是数字。
以下是我尝试过的内容的总结:
设置数据帧数据类型。我通过了一个 dict 并得到了我预期的结果。当我做 print(df.dtypes)
我得到 {'PehRecID': 'float64', 'PehAccrualCode': 'object', ....
所以我已经成功地设置了数据类型。
使用以下代码将列显式转换为 float64:
df['PehRecID'] = df['PehRecID'].astype('float64')
当我尝试 df.to_parquet('foo.parquet', engine='pyarrow')
我得到 ValueError: could not convert string to float: 'PehRecID'
当我尝试 print(df.head())
我也 get ValueError: could not convert string to float: 'PehRecID'
看来问题出在 Dask,而不是 Parquet。
我正在处理的文件有时对于 Pandas 来说太大了,但并不大。在这种情况下,我实际上是在尝试使用一个相当小的文件来获得正确的基础知识。
使用 dask 时,了解 dask evaluates tasks lazily and asynchronously 很重要,这意味着当您输入命令时,dash 会安排 但不会执行命令 直到需要(因为 write
、compute
、print
、head
或其他命令需要为该步骤计算结果)。这意味着错误可能会作为一个步骤的结果发生,但您可能要等到稍后执行几个命令后才会发现错误,然后再恢复可能为时已晚。
在您的情况下,df['PehRecID'] = df['PehRecID'].astype('float64')
似乎是罪魁祸首。您在稍后的步骤中收到错误 ValueError: could not convert string to float: 'PehRecID'
,例如 df.head()
,因为您已将带有错误 的命令 的结果分配给数据帧列,使该列不可用。
作为一个非常简单的例子,让我们创建一个包含四个字符串值的 dask 数据帧,其中前三个可以转换为 int,最后一个不能:
In [4]: df = ddf.from_pandas(
...: pd.DataFrame({'A': ['1', '2', '3', 'not a value']}),
...: npartitions=2,
...: )
...:
In [5]: df
Out[5]:
Dask DataFrame Structure:
A
npartitions=2
0 object
2 ...
3 ...
Dask Name: from_pandas, 2 tasks
请注意,调用 df.astype(int)
不会引发错误 - 这是因为您只安排了操作 - 您还没有实际执行它:
In [6]: df.astype(int)
Out[6]:
Dask DataFrame Structure:
A
npartitions=2
0 int64
2 ...
3 ...
Dask Name: astype, 4 tasks
请注意,dtypes 现在显示 int64
,因为这是 .astype(int)
操作的结果指示的数据类型。
计算结果确实引发了预期的错误:
In [7]: df.astype(int).compute()
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-7-05b64497024c> in <module>
----> 1 df.astype(int).compute()
...
ValueError: invalid literal for int() with base 10: 'not a value'
如果就地分配结果,您可能 运行 遇到麻烦:
In [8]: df['A'] = df['A'].astype(int)
同样,数据框的 dtype 已更改以反映 .astype(int)
的预期输出:
In [9]: df.dtypes
Out[9]:
A int64
dtype: object
效果是现在无法计算df:
In [10]: df.compute()
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-14-9bb416d45ef6> in <module>
----> 1 df.compute()
...
ValueError: invalid literal for int() with base 10: 'not a value'
请注意,如果请求的分区中没有发生错误,则可以屏蔽此问题。在我的例子中,错误发生在第二个分区,所以只使用第一个分区的df.head()
,只触发第一个分区的astype(int)
操作,不报错:
In [11]: df.head()
/Users/delgadom/miniconda3/envs/rhodium-env/lib/python3.9/site-packages/dask/dataframe/core.py:6383: UserWarning: Insufficient elements for `head`. 5 elements requested, only 2 elements available. Try passing larger `npartitions` to `head`.
warnings.warn(msg.format(n, len(r)))
Out[11]:
A
0 1
1 2
如果不完全废弃列或数据帧并重新读取数据,这可能无法从中恢复,因为您已经用未来可靠地生成错误重写了列 A 的内容。
所以我认为您的特定问题的答案是您的数据不干净 - 您的列中某处确实有字符串。