从 NumPy 掩码数组创建 Pandas DataFrame?
Creating a Pandas DataFrame from a NumPy masked array?
我正在尝试从 NumPy 掩码数组创建 Pandas DataFrame
,我知道这是受支持的操作。这是源数组的示例:
a = ma.array([(1, 2.2), (42, 5.5)],
dtype=[('a',int),('b',float)],
mask=[(True,False),(False,True)])
输出为:
masked_array(data=[(--, 2.2), (42, --)],
mask=[( True, False), (False, True)],
fill_value=(999999, 1.e+20),
dtype=[('a', '<i8'), ('b', '<f8')])
正在尝试用 pd.DataFrame(a)
创建一个 DataFrame
returns:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-40-a4c5236a3cd4> in <module>
----> 1 pd.DataFrame(a)
/usr/local/anaconda/lib/python3.8/site-packages/pandas/core/frame.py in __init__(self, data, index, columns, dtype, copy)
636 # a masked array
637 else:
--> 638 data = sanitize_masked_array(data)
639 mgr = ndarray_to_mgr(
640 data,
/usr/local/anaconda/lib/python3.8/site-packages/pandas/core/construction.py in sanitize_masked_array(data)
452 """
453 mask = ma.getmaskarray(data)
--> 454 if mask.any():
455 data, fill_value = maybe_upcast(data, copy=True)
456 data.soften_mask() # set hardmask False if it was True
/usr/local/anaconda/lib/python3.8/site-packages/numpy/core/_methods.py in _any(a, axis, dtype, out, keepdims, where)
54 # Parsing keyword arguments is currently fairly slow, so avoid it for now
55 if where is True:
---> 56 return umr_any(a, axis, dtype, out, keepdims)
57 return umr_any(a, axis, dtype, out, keepdims, where=where)
58
TypeError: cannot perform reduce with flexible type
确实支持这个操作吗?目前使用 Pandas 1.3.3 和 NumPy 1.20.3.
更新
支持吗?
根据 Pandas documentation here:
Alternatively, you may pass a numpy.MaskedArray as the data argument to the DataFrame constructor, and its masked entries will be considered missing.
上面的代码是我问的问题“我会得到什么?”如果我将 NumPy 掩码数组传递给 Pandas,但这是我希望的结果。以上是我能想到的最简单的例子。
我希望 Pandas 中的每个 Series/column 都是单一类型。
更新 2
任何对此感兴趣的人都应该看到这个 Pandas GitHub issue;那里注意到 Pandas 已经“弃用了对 MaskedRecords 的支持”。
问题是你希望得到什么? pandas 转换您的数据会产生歧义。
如果要获取原始数据:
>>> pd.DataFrame(a.data)
a b
0 1 2.2
1 42 5.5
如果您认为掩码值无效:
>>> pd.DataFrame(a.filled(np.nan))
BUT,为此你应该在掩码数组中拥有所有类型的浮点数
如果数组有一个简单的 dtype,则数据框创建有效(如文档所述):
In [320]: a = np.ma.array([(1, 2.2), (42, 5.5)],
...: mask=[(True,False),(False,True)])
In [321]: a
Out[321]:
masked_array(
data=[[--, 2.2],
[42.0, --]],
mask=[[ True, False],
[False, True]],
fill_value=1e+20)
In [322]: import pandas as pd
In [323]: pd.DataFrame(a)
Out[323]:
0 1
0 NaN 2.2
1 42.0 NaN
这个a
是(2,2),结果是2行2列
使用复合 dtype,形状为 1d:
In [326]: a = np.ma.array([(1, 2.2), (42, 5.5)],
...: dtype=[('a',int),('b',float)],
...: mask=[(True,False),(False,True)])
In [327]: a.shape
Out[327]: (2,)
错误是面具测试的结果。 flexible type
指的是你的化合物 dtype
:
In [330]: a.mask.any()
Traceback (most recent call last):
File "<ipython-input-330-8dc32ee3f59d>", line 1, in <module>
a.mask.any()
File "/usr/local/lib/python3.8/dist-packages/numpy/core/_methods.py", line 57, in _any
return umr_any(a, axis, dtype, out, keepdims)
TypeError: cannot perform reduce with flexible type
记录的 pandas 功能显然不适用于结构化数组。在不研究 pandas 代码的情况下,我无法确切地说出它此时正在尝试做什么,但很明显代码在编写时并未考虑结构化数组。
非屏蔽部分确实有效,具有所需的列数据类型:
In [332]: pd.DataFrame(a.data)
Out[332]:
a b
0 1 2.2
1 42 5.5
使用默认 fill
:
In [344]: a.filled()
Out[344]:
array([(999999, 2.2e+00), ( 42, 1.0e+20)],
dtype=[('a', '<i8'), ('b', '<f8')])
In [345]: pd.DataFrame(a.filled())
Out[345]:
a b
0 999999 2.200000e+00
1 42 1.000000e+20
我必须多看看 ma
docs/code 看看是否可以对这两个字段应用不同的填充。用 nan
填充对 int 字段不起作用。 numpy
没有 pandas'
int none。我还没有充分利用 pandas 功能来了解生成的 dtype 是否仍然是 int,或者它已更改为对象。
无论如何,您正在通过此任务突破 np.ma
和 pandas
的界限。
编辑
默认fill_value是一个元组,每个字段一个:
In [350]: a.fill_value
Out[350]: (999999, 1.e+20)
所以我们可以用不同的方式填充字段,并从中制作一个框架:
In [351]: a.filled((-1, np.nan))
Out[351]: array([(-1, 2.2), (42, nan)], dtype=[('a', '<i8'), ('b', '<f8')])
In [352]: pd.DataFrame(a.filled((-1, np.nan)))
Out[352]:
a b
0 -1 2.2
1 42 NaN
看起来我可以用 pandas dtype 及其关联的 fill_value:
创建一个结构化数组
In [363]: a = np.ma.array([(1, 2.2), (42, 5.5)],
...: dtype=[('a',pd.Int64Dtype),('b',float)],
...: mask=[(True,False),(False,True)],
fill_value=(pd.NA,np.nan))
In [364]: a
Out[364]:
masked_array(data=[(--, 2.2), (42, --)],
mask=[( True, False), (False, True)],
fill_value=(<NA>, nan),
dtype=[('a', 'O'), ('b', '<f8')])
In [366]: pd.DataFrame(a.filled())
Out[366]:
a b
0 <NA> 2.2
1 42 NaN
我正在尝试从 NumPy 掩码数组创建 Pandas DataFrame
,我知道这是受支持的操作。这是源数组的示例:
a = ma.array([(1, 2.2), (42, 5.5)],
dtype=[('a',int),('b',float)],
mask=[(True,False),(False,True)])
输出为:
masked_array(data=[(--, 2.2), (42, --)],
mask=[( True, False), (False, True)],
fill_value=(999999, 1.e+20),
dtype=[('a', '<i8'), ('b', '<f8')])
正在尝试用 pd.DataFrame(a)
创建一个 DataFrame
returns:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-40-a4c5236a3cd4> in <module>
----> 1 pd.DataFrame(a)
/usr/local/anaconda/lib/python3.8/site-packages/pandas/core/frame.py in __init__(self, data, index, columns, dtype, copy)
636 # a masked array
637 else:
--> 638 data = sanitize_masked_array(data)
639 mgr = ndarray_to_mgr(
640 data,
/usr/local/anaconda/lib/python3.8/site-packages/pandas/core/construction.py in sanitize_masked_array(data)
452 """
453 mask = ma.getmaskarray(data)
--> 454 if mask.any():
455 data, fill_value = maybe_upcast(data, copy=True)
456 data.soften_mask() # set hardmask False if it was True
/usr/local/anaconda/lib/python3.8/site-packages/numpy/core/_methods.py in _any(a, axis, dtype, out, keepdims, where)
54 # Parsing keyword arguments is currently fairly slow, so avoid it for now
55 if where is True:
---> 56 return umr_any(a, axis, dtype, out, keepdims)
57 return umr_any(a, axis, dtype, out, keepdims, where=where)
58
TypeError: cannot perform reduce with flexible type
确实支持这个操作吗?目前使用 Pandas 1.3.3 和 NumPy 1.20.3.
更新
支持吗? 根据 Pandas documentation here:
Alternatively, you may pass a numpy.MaskedArray as the data argument to the DataFrame constructor, and its masked entries will be considered missing.
上面的代码是我问的问题“我会得到什么?”如果我将 NumPy 掩码数组传递给 Pandas,但这是我希望的结果。以上是我能想到的最简单的例子。
我希望 Pandas 中的每个 Series/column 都是单一类型。
更新 2
任何对此感兴趣的人都应该看到这个 Pandas GitHub issue;那里注意到 Pandas 已经“弃用了对 MaskedRecords 的支持”。
问题是你希望得到什么? pandas 转换您的数据会产生歧义。
如果要获取原始数据:
>>> pd.DataFrame(a.data)
a b
0 1 2.2
1 42 5.5
如果您认为掩码值无效:
>>> pd.DataFrame(a.filled(np.nan))
BUT,为此你应该在掩码数组中拥有所有类型的浮点数
如果数组有一个简单的 dtype,则数据框创建有效(如文档所述):
In [320]: a = np.ma.array([(1, 2.2), (42, 5.5)],
...: mask=[(True,False),(False,True)])
In [321]: a
Out[321]:
masked_array(
data=[[--, 2.2],
[42.0, --]],
mask=[[ True, False],
[False, True]],
fill_value=1e+20)
In [322]: import pandas as pd
In [323]: pd.DataFrame(a)
Out[323]:
0 1
0 NaN 2.2
1 42.0 NaN
这个a
是(2,2),结果是2行2列
使用复合 dtype,形状为 1d:
In [326]: a = np.ma.array([(1, 2.2), (42, 5.5)],
...: dtype=[('a',int),('b',float)],
...: mask=[(True,False),(False,True)])
In [327]: a.shape
Out[327]: (2,)
错误是面具测试的结果。 flexible type
指的是你的化合物 dtype
:
In [330]: a.mask.any()
Traceback (most recent call last):
File "<ipython-input-330-8dc32ee3f59d>", line 1, in <module>
a.mask.any()
File "/usr/local/lib/python3.8/dist-packages/numpy/core/_methods.py", line 57, in _any
return umr_any(a, axis, dtype, out, keepdims)
TypeError: cannot perform reduce with flexible type
记录的 pandas 功能显然不适用于结构化数组。在不研究 pandas 代码的情况下,我无法确切地说出它此时正在尝试做什么,但很明显代码在编写时并未考虑结构化数组。
非屏蔽部分确实有效,具有所需的列数据类型:
In [332]: pd.DataFrame(a.data)
Out[332]:
a b
0 1 2.2
1 42 5.5
使用默认 fill
:
In [344]: a.filled()
Out[344]:
array([(999999, 2.2e+00), ( 42, 1.0e+20)],
dtype=[('a', '<i8'), ('b', '<f8')])
In [345]: pd.DataFrame(a.filled())
Out[345]:
a b
0 999999 2.200000e+00
1 42 1.000000e+20
我必须多看看 ma
docs/code 看看是否可以对这两个字段应用不同的填充。用 nan
填充对 int 字段不起作用。 numpy
没有 pandas'
int none。我还没有充分利用 pandas 功能来了解生成的 dtype 是否仍然是 int,或者它已更改为对象。
无论如何,您正在通过此任务突破 np.ma
和 pandas
的界限。
编辑
默认fill_value是一个元组,每个字段一个:
In [350]: a.fill_value
Out[350]: (999999, 1.e+20)
所以我们可以用不同的方式填充字段,并从中制作一个框架:
In [351]: a.filled((-1, np.nan))
Out[351]: array([(-1, 2.2), (42, nan)], dtype=[('a', '<i8'), ('b', '<f8')])
In [352]: pd.DataFrame(a.filled((-1, np.nan)))
Out[352]:
a b
0 -1 2.2
1 42 NaN
看起来我可以用 pandas dtype 及其关联的 fill_value:
创建一个结构化数组In [363]: a = np.ma.array([(1, 2.2), (42, 5.5)],
...: dtype=[('a',pd.Int64Dtype),('b',float)],
...: mask=[(True,False),(False,True)],
fill_value=(pd.NA,np.nan))
In [364]: a
Out[364]:
masked_array(data=[(--, 2.2), (42, --)],
mask=[( True, False), (False, True)],
fill_value=(<NA>, nan),
dtype=[('a', 'O'), ('b', '<f8')])
In [366]: pd.DataFrame(a.filled())
Out[366]:
a b
0 <NA> 2.2
1 42 NaN