【问题标题】:Pandas dataframe with dynamically built columns, and integer data with NaN?带有动态构建列的 Pandas 数据框和带有 NaN 的整数数据?
【发布时间】:2020-04-02 10:05:41
【问题描述】:

我见过Insert rows into pandas DataFrame while maintaining column data types,我知道

由于 NaN 是浮点数,将 NaN 添加到系列可能会导致它向上转换为浮点数或转换为对象。

...但我无法从这些帖子中真正看出我的用例是否有解决方案:

所以,我想动态构建一个 pandas DataFrame,从一个已定义的列开始,然后添加更多列 - 全部包含整数数据;因此,显然某些行值将是未定义的,即 NaN。这是一个简短的例子:

import pandas as pd
print("pandas.__version__ {}".format(pd.__version__))

# initialize dataframe with one column
test_df = pd.DataFrame(columns=["time"])

# "append column" - add data with a newly defined column
test_df = test_df.append({'time': 20, 'varA': 14}, ignore_index=True)

# (same)
test_df = test_df.append({'time': 5673547, 'varB': 78}, ignore_index=True)

# (same)
test_df = test_df.append({'time': 9480530495459073, 'varC': 4567457}, ignore_index=True)

print(test_df)
print(test_df.astype(pd.Int64Dtype()))

打印出来:

pandas.__version__ 1.0.2
          time  varA  varB       varC
0           20  14.0   NaN        NaN
1  5.67355e+06   NaN  78.0        NaN
2  9.48053e+15   NaN   NaN  4567457.0
               time  varA  varB     varC
0                20    14  <NA>     <NA>
1           5673547  <NA>    78     <NA>
2  9480530495459072  <NA>  <NA>  4567457

所以,虽然我可以通过将 DataFrame 构建为浮点数来解决这个问题,然后将其转换为整数 - 请注意我已经指定了 9480530495459073 - 但是,在转换之后,我得到了 9480530495459072 打印,这是一个不可接受的错误对于我的用例。

我是否有任何其他选项来构建这样的 DataFrame(使用整数数据,并动态添加新列 - 这将导致丢失/未定义/NaN 值),以便它在内部使用整数? (或者可能在内部使用其他数据类型,只要我不丢失整数精度?)

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    如果您想要Int64,您可以将您的字典转换为具有该dtype 的系列:

    # initialize dataframe with one column
    test_df = pd.DataFrame(columns=["time"])
    
    # append many times, create a function
    def append(df, d):
        return df.append(pd.Series(d, dtype='Int64'), ignore_index=True)
    
    # "append column" - add data with a newly defined column
    test_df = append(test_df, {'time': 20, 'varA': 14})
    
    # (same)
    test_df = append(test_df, {'time': 5673547, 'varB': 78})
    
    # (same)
    test_df = append(test_df, {'time': 9480530495459073, 'varC': 4567457})
    

    输出:

                   time  varA  varB     varC
    0                20    14   NaN      NaN
    1           5673547  <NA>    78      NaN
    2  9480530495459073  <NA>  <NA>  4567457
    

    【讨论】:

    • 非常感谢@QuangHoang - 我在与此相关的不同帖子中看到了 pd.Series,但我不知道如何将其应用于我的用例;你的回答解释了它。谢谢!
    【解决方案2】:

    将其作为实际数据框附加是否可以解决您的问题?如果您想防止它们成为对象,可以选择在原始 test_df 中传递 dtype='int'。

    import pandas as pd
    print("pandas.__version__ {}".format(pd.__version__))
    
    # initialize dataframe with one column
    test_df = pd.DataFrame(columns=["time"])
    
    # "append column" - add data with a newly defined column
    test_df = test_df.append(pd.DataFrame({'time': [20], 'varA': [14]}), ignore_index=True)
    
    # # (same)
    test_df = test_df.append(pd.DataFrame({'time': [5673547], 'varB': [78]}), ignore_index=True)
    
    # # (same)
    test_df = test_df.append(pd.DataFrame({'time': [9480530495459073], 'varC': [4567457]}), ignore_index=True)
    
    print(test_df)
    print(test_df.astype(pd.Int64Dtype()))
    
    pandas.__version__ 1.0.1
                   time  varA  varB       varC
    0                20  14.0   NaN        NaN
    1           5673547   NaN  78.0        NaN
    2  9480530495459073   NaN   NaN        4567457.0
                   time  varA  varB     varC
    0                20    14  <NA>     <NA>
    1           5673547  <NA>    78     <NA>
    2  9480530495459073  <NA>  <NA>     4567457
    

    【讨论】:

    • 谢谢@Chris - 我想这不是真的,因为从您的打印输出中可以看出,test_df 仍然在内部浮动(尽管,time 列似乎不是,并且它是整数),这意味着当您转换为 pd.Int64Dtype 时仍然可能会丢失精度(尽管有趣的是,您的 time 列的打印输出显示了正确的 9480530495459073 - 但也许那是因为这里只有 time 列内部是int;……啊,可能是因为time 列这里没有NaN!)。
    猜你喜欢
    • 2020-04-11
    • 2021-09-22
    • 2019-05-16
    • 1970-01-01
    • 2017-10-20
    • 2021-02-06
    • 2018-02-23
    • 2019-03-24
    • 2019-08-11
    相关资源
    最近更新 更多