【问题标题】:pandas interpolate with nearest for non-numeric values大熊猫用最接近的非数字值进行插值
【发布时间】:2017-09-21 00:21:44
【问题描述】:

我有一个带有日期时间索引的数字和非数字值的数据框:

df = pd.DataFrame([
    {'date': datetime(2017, 4, 24, 1), 'a':1, 'b':2, 'c': "hee"},
    {'date': datetime(2017, 4, 24, 2), 'a':2, 'b':4, 'c': 'hoo'},
    {'date': datetime(2017, 4, 24, 3), 'a':4, 'b':8, 'c': 'joo'},
    {'date': datetime(2017, 4, 24, 4), 'a':8, 'b':16, 'c': 'jee'}
]).set_index('date')

我想:

  • 线性插值数值;和
  • 获取非数字值的最接近值。

最优雅的实现是什么?

策略 1

全部插值,然后fillna

df = df.resample('20T').interpolate('linear')
df.fillna(method='nearest')

但是...nearest 方法没有实现。

策略 2

拆分数字列和非数字列

df2 = df.resample('20T')
df_a = df2._get_numeric_data().interpolate('linear')
df_b = df2[list(set(df.columns) - set(set(df_a.columns)))].interpolate('nearest')

给出错误:

TypeError:无法使用所有 NaN 进行插值。

更新

使用最近的方法进行插值,确实适用于布尔值和数值,但不适用于字符串,例如:

df.resample('20T').intepolate('nearest')

【问题讨论】:

    标签: python-3.x pandas datetime


    【解决方案1】:

    由于interpolate("nearest") 可以很好地处理数字类型,因此解决方案是:

    1. 将您的列从字符串转换为分类(即数字)
    2. interpolate("nearest") 插入分类
    3. 映射回字符串插值分类列

      def fillna_nearest(series):
          fact = series.astype('category').factorize()
      
          series_cat = pd.Series(fact[0]).replace(-1, np.nan) # get string as categorical (-1 is NaN)
          series_cat_interp = series_cat.interpolate("nearest") # interpolate categorical
      
          cat_to_string = {i:x for i,x in enumerate(fact[1])} # dict connecting category to string
          series_str_interp = series_cat_interp.map(cat_to_string) # turn category back to string
      
          return series_str_interp
      
      
      In [10]: df.resample('20T').interpolate().apply(fillna_nearest)
      Out[10]: 
                a          b    c
      0  1.000000   2.000000  hee
      1  1.333333   2.666667  hee
      2  1.666667   3.333333  hoo
      3  2.000000   4.000000  hoo
      4  2.666667   5.333333  hoo
      5  3.333333   6.666667  joo
      6  4.000000   8.000000  joo
      7  5.333333  10.666667  joo
      8  6.666667  13.333333  jee
      9  8.000000  16.000000  jee
      

    【讨论】:

      【解决方案2】:

      这是你想要的吗?

      In [22]: df.resample('20T').interpolate().ffill()
      Out[22]:
                                  a          b    c
      date
      2017-04-24 01:00:00  1.000000   2.000000  hee
      2017-04-24 01:20:00  1.333333   2.666667  hee
      2017-04-24 01:40:00  1.666667   3.333333  hee
      2017-04-24 02:00:00  2.000000   4.000000  hoo
      2017-04-24 02:20:00  2.666667   5.333333  hoo
      2017-04-24 02:40:00  3.333333   6.666667  hoo
      2017-04-24 03:00:00  4.000000   8.000000  joo
      2017-04-24 03:20:00  5.333333  10.666667  joo
      2017-04-24 03:40:00  6.666667  13.333333  joo
      2017-04-24 04:00:00  8.000000  16.000000  jee
      

      【讨论】:

      • 几乎,C列没有用“最近”方法插值,第3个值应该等于第4个值
      • @API,我没有正确理解你。列c - 是一个字符串列 - 我们不能插入它
      • 因此它应该得到最接近的值而不是前向填充
      • @API,您能否为字符串的“最近”方法定义一个算法?
      • 列应该变成:'hee', 'hee', 'hoo', 'hoo', 'hoo', 'joo', 'joo', 'joo', 'jee', 'jee '。因为这些是最接近的值。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-28
      • 2017-07-25
      • 2021-09-04
      • 2018-12-08
      • 2022-01-23
      相关资源
      最近更新 更多