Python 如何在构造数据帧时填充缺少的值?

Python 如何在构造数据帧时填充缺少的值?,python,pandas,Python,Pandas,我使用pandas来存储一个大但非常稀疏的矩阵(50000行*100000列),这个矩阵的每个元素都是一个从0.00到1.00的浮点数。原始元素值存储在python dict中(仅存储已知值的元素) 现在的问题是如何从dict有效地构造pandas.DataFrame 如果我使用float64,那么这个矩阵的物理大小的粗略估计将是:(50000*100000*8)=37GB,这大大大于我机器的内存大小 但是,我注意到,由于每个元素的范围是从0.00到1.00,我只关心前2位数字,所以我可以通过乘

我使用pandas来存储一个大但非常稀疏的矩阵(50000行*100000列),这个矩阵的每个元素都是一个从0.00到1.00的浮点数。原始元素值存储在python dict中(仅存储已知值的元素)

现在的问题是如何从dict有效地构造pandas.DataFrame

如果我使用float64,那么这个矩阵的物理大小的粗略估计将是:(50000*100000*8)=37GB,这大大大于我机器的内存大小

但是,我注意到,由于每个元素的范围是从0.00到1.00,我只关心前2位数字,所以我可以通过乘以100将每个元素转换为无符号8位整数,然后转换为np.uint8,这可以将此数据帧减少到可接受的大小:(1/8*37GB)

我尝试了这种方法,但是pandas.DataFrame没有像我预期的那样工作。当我在pd.DataFrame()构造函数中指定dtype时,最终结果仍然是float64

下面是一个示例代码:

In [87]: dc = {'A':{'a':np.uint8(1.2), 'c':np.uint8(3.2)}, 'B':{'a':np.uint8(1.2), \
               'b':np.uint8(2.2)}, 'C':{'b':np.uint8(2.2), 'd':np.uint8(4.2)}}

In [88]: dc
Out[88]: {'A': {'a': 1, 'c': 3}, 'B': {'a': 1, 'b': 2}, 'C': {'b': 2, 'd': 4}}

In [89]: type(dc['A']['a'])
Out[89]: numpy.uint8

In [90]: df = pd.DataFrame(dc, index=['a', 'b', 'c','d'], dtype=np.uint8)

In [91]: df
Out[91]: 
    A   B   C
a   1   1 NaN
b NaN   2   2
c   3 NaN NaN
d NaN NaN   4

In [92]: df.dtypes
Out[92]: 
A    float64
B    float64
C    float64
dtype: object

@zero323提到这是pandas的一种设计选择,那么,有没有任何方法可以有效地构建此数据帧?

这对您没有帮助,但这是一种预期行为。引用

当通过reindex或其他方式将NAs引入现有系列或数据帧时,布尔和整数类型将升级为不同的数据类型以存储NAs

@EdChum的评论提供了最佳解决方案,但如果您真的需要使用dicts,那么您可以尝试以下方法:

# Choose some default value
default = 0
# Prepare dict with defaults
defaults = {k: default for k in chain(*(x.keys() for x in dc.values()))}

# Fill gaps if needed and construct data frame
df = pd.DataFrame(
    {k: dict(defaults.items() + v.items()) for k, v in dc.items()},
    index=['a', 'b', 'c','d'], dtype=np.uint8)

发生这种情况的原因是,
NaN
不能用整数表示,一旦出现这种情况,数据类型将转换为适当的类型,在本例中为float。因此,您必须决定是否删除
NaN
值,将其替换为0或其他可以用
int
@EdChum表示的值。谢谢,有没有办法构造pandas.DataFrame并同时填充缺少的值?没有,它必须在构建之后完成,或者你必须自己填充缺失的值,而不是直接使用DITCS,但是NUMPY数组将有各种方法来填充空白,另一个要考虑的是@ ICEXLILN,我已经发布了更新。这不是最有效的方法,但如果对你有效,你可以尝试一下。