【问题标题】:Is there a way to prevent dtype from changing from Int64 to float64 when reindexing/upsampling a time-series?在重新索引/上采样时间序列时,有没有办法防止 dtype 从 Int64 更改为 float64?
【发布时间】:2017-01-06 05:43:45
【问题描述】:

我正在使用 pandas 0.17.0 并且有一个类似于这个的 df

df.head()
Out[339]: 
                       A     B  C
DATE_TIME                        
2016-10-08 13:57:00  in   5.61  1
2016-10-08 14:02:00  in   8.05  1
2016-10-08 14:07:00  in   7.92  0
2016-10-08 14:12:00  in   7.98  0
2016-10-08 14:17:00  out  8.18  0

df.tail()
Out[340]: 
                       A     B  C
DATE_TIME                        
2016-11-08 13:42:00  in   8.00  0
2016-11-08 13:47:00  in   7.99  0
2016-11-08 13:52:00  out  7.97  0
2016-11-08 13:57:00  in   8.14  1
2016-11-08 14:02:00  in   8.16  1

关注dtypes:

print (df.dtypes)
A     object
B    float64
C      int64
dtype: object

当我将df 重新索引到分钟间隔时,所有列int64 都更改为float64

index = pd.date_range(df.index[0], df.index[-1], freq="min") 
df2 = df.reindex(index)

print (df2.dtypes)
A     object
B    float64
C    float64
dtype: object

另外,如果我尝试重新采样

df3 = df.resample('Min')

int64 将变成float64,由于某种原因我失去了我的object 列。

print (df3.dtypes)

print (df3.dtypes)
B    float64
C    float64
dtype: object

由于我想在后续步骤中根据这种区别对列进行不同的插值(在将df 与另一个df 连接后),我需要它们保持原来的dtype。我真正的df 每种类型的列要多得多,因此我正在寻找一种不依赖于通过标签单独调用列的解决方案。

有没有办法在整个重新索引过程中保持他们的dtype?或者有没有办法我可以在之后为它们分配dtype(它们是除了 NAN 之外唯一只包含整数的列)? 有人可以帮帮我吗?

【问题讨论】:

    标签: python pandas types resampling reindex


    【解决方案1】:

    它是impossible,因为如果在某列中至少有一个NaN 值,int 将转换为float

    index = pd.date_range(df.index[0], df.index[-1], freq="min") 
    df2 = df.reindex(index)
    
    print (df2)
                           A     B    C
    2016-10-08 13:57:00   in  5.61  1.0
    2016-10-08 13:58:00  NaN   NaN  NaN
    2016-10-08 13:59:00  NaN   NaN  NaN
    2016-10-08 14:00:00  NaN   NaN  NaN
    2016-10-08 14:01:00  NaN   NaN  NaN
    2016-10-08 14:02:00   in  8.05  1.0
    2016-10-08 14:03:00  NaN   NaN  NaN
    2016-10-08 14:04:00  NaN   NaN  NaN
    2016-10-08 14:05:00  NaN   NaN  NaN
    2016-10-08 14:06:00  NaN   NaN  NaN
    2016-10-08 14:07:00   in  7.92  0.0
    2016-10-08 14:08:00  NaN   NaN  NaN
    2016-10-08 14:09:00  NaN   NaN  NaN
    2016-10-08 14:10:00  NaN   NaN  NaN
    2016-10-08 14:11:00  NaN   NaN  NaN
    2016-10-08 14:12:00   in  7.98  0.0
    2016-10-08 14:13:00  NaN   NaN  NaN
    2016-10-08 14:14:00  NaN   NaN  NaN
    2016-10-08 14:15:00  NaN   NaN  NaN
    2016-10-08 14:16:00  NaN   NaN  NaN
    2016-10-08 14:17:00  out  8.18  0.0
    
    print (df2.dtypes)
    A     object
    B    float64
    C    float64
    dtype: object
    

    但如果在reindex中使用参数fill_valuedtypes不会改变:

    index = pd.date_range(df.index[0], df.index[-1], freq="min") 
    df2 = df.reindex(index, fill_value=0)
    
    print (df2)
                           A     B  C
    2016-10-08 13:57:00   in  5.61  1
    2016-10-08 13:58:00    0  0.00  0
    2016-10-08 13:59:00    0  0.00  0
    2016-10-08 14:00:00    0  0.00  0
    2016-10-08 14:01:00    0  0.00  0
    2016-10-08 14:02:00   in  8.05  1
    2016-10-08 14:03:00    0  0.00  0
    2016-10-08 14:04:00    0  0.00  0
    2016-10-08 14:05:00    0  0.00  0
    2016-10-08 14:06:00    0  0.00  0
    2016-10-08 14:07:00   in  7.92  0
    2016-10-08 14:08:00    0  0.00  0
    2016-10-08 14:09:00    0  0.00  0
    2016-10-08 14:10:00    0  0.00  0
    2016-10-08 14:11:00    0  0.00  0
    2016-10-08 14:12:00   in  7.98  0
    2016-10-08 14:13:00    0  0.00  0
    2016-10-08 14:14:00    0  0.00  0
    2016-10-08 14:15:00    0  0.00  0
    2016-10-08 14:16:00    0  0.00  0
    2016-10-08 14:17:00  out  8.18  0
    
    print (df2.dtypes)
    A     object
    B    float64
    C      int64
    dtype: object
    

    reindex 中使用method='ffill 更好:

    index = pd.date_range(df.index[0], df.index[-1], freq="min") 
    df2 = df.reindex(index, method='ffill')
    
    print (df2)
                           A     B  C
    2016-10-08 13:57:00   in  5.61  1
    2016-10-08 13:58:00   in  5.61  1
    2016-10-08 13:59:00   in  5.61  1
    2016-10-08 14:00:00   in  5.61  1
    2016-10-08 14:01:00   in  5.61  1
    2016-10-08 14:02:00   in  8.05  1
    2016-10-08 14:03:00   in  8.05  1
    2016-10-08 14:04:00   in  8.05  1
    2016-10-08 14:05:00   in  8.05  1
    2016-10-08 14:06:00   in  8.05  1
    2016-10-08 14:07:00   in  7.92  0
    2016-10-08 14:08:00   in  7.92  0
    2016-10-08 14:09:00   in  7.92  0
    2016-10-08 14:10:00   in  7.92  0
    2016-10-08 14:11:00   in  7.92  0
    2016-10-08 14:12:00   in  7.98  0
    2016-10-08 14:13:00   in  7.98  0
    2016-10-08 14:14:00   in  7.98  0
    2016-10-08 14:15:00   in  7.98  0
    2016-10-08 14:16:00   in  7.98  0
    2016-10-08 14:17:00  out  8.18  0
    
    print (df2.dtypes)
    A     object
    B    float64
    C      int64
    dtype: object
    

    如果使用resample,你可以通过unstackstack返回A列,但不幸的是float仍然存在问题:

    df3 = df.set_index('A', append=True)
            .unstack()
            .resample('Min', fill_method='ffill')
            .stack()
            .reset_index(level=1)
    print (df3)
                           A     B    C
    DATE_TIME                          
    2016-10-08 13:57:00   in  5.61  1.0
    2016-10-08 13:58:00   in  5.61  1.0
    2016-10-08 13:59:00   in  5.61  1.0
    2016-10-08 14:00:00   in  5.61  1.0
    2016-10-08 14:01:00   in  5.61  1.0
    2016-10-08 14:02:00   in  8.05  1.0
    2016-10-08 14:03:00   in  8.05  1.0
    2016-10-08 14:04:00   in  8.05  1.0
    2016-10-08 14:05:00   in  8.05  1.0
    2016-10-08 14:06:00   in  8.05  1.0
    2016-10-08 14:07:00   in  7.92  0.0
    2016-10-08 14:08:00   in  7.92  0.0
    2016-10-08 14:09:00   in  7.92  0.0
    2016-10-08 14:10:00   in  7.92  0.0
    2016-10-08 14:11:00   in  7.92  0.0
    2016-10-08 14:12:00   in  7.98  0.0
    2016-10-08 14:13:00   in  7.98  0.0
    2016-10-08 14:14:00   in  7.98  0.0
    2016-10-08 14:15:00   in  7.98  0.0
    2016-10-08 14:16:00   in  7.98  0.0
    2016-10-08 14:17:00  out  8.18  0.0
    
    print (df3.dtypes)
    A     object
    B    float64
    C    float64
    dtype: object
    

    我尝试修改之前的 answer 以转换为 `int:

    int_cols = df.select_dtypes(['int64']).columns
    print (int_cols)
    Index(['C'], dtype='object')
    
    index = pd.date_range(df.index[0], df.index[-1], freq="s")
    df2 = df.reindex(index)
    
    for col in df2:
        if col == int_cols: 
            df2[col].ffill(inplace=True)
            df2[col] = df2[col].astype(int)
        elif df2[col].dtype == float:
            df2[col].interpolate(inplace=True)
        else:
            df2[col].ffill(inplace=True)
    
    #print (df2)
    
    print (df2.dtypes)
    A     object
    B    float64
    C      int32
    dtype: object
    

    【讨论】:

    • 非常感谢!我想我现在的问题是,我无法将float64 作为下一步线性插值,因为所有新创建的时间步都已填满。 link。这是我原来问题的链接,我今天才意识到接受的解决方案中的 dtype 存在问题,这就是我发布这个新问题的原因。你觉得我真正想要的有可能吗?
    • 我添加了解决方案,请查看上次更新。感谢您的接受!
    • 酷!该代码在我的示例df 上的工作方式与此类似,但要使其与我的真实df 一起使用,每种类型的多个列我必须修改以下行if col == int_cols.all():,因为我确实收到了错误:ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()。现在它似乎工作得很好!再次感谢!
    猜你喜欢
    • 2017-07-07
    • 2012-11-19
    • 2017-01-03
    • 1970-01-01
    • 2020-06-08
    • 2018-06-30
    • 2018-08-17
    • 2012-02-03
    • 2011-02-28
    相关资源
    最近更新 更多