【问题标题】:Find closest valid numbers among missing values in a pandas dataframe在 pandas 数据框中的缺失值中查找最接近的有效数字
【发布时间】:2018-12-11 22:40:28
【问题描述】:

我有一个数据集,其中包含多个不同长度的缺失序列,我想在其中找到在某些特定日期在这些序列之前和之后出现的第一个有效数字。在下面的示例数据集中,我想找到最接近日期2018-11-26ColumnB 的有效数字。

数据样本:

Date         ColumnA   ColumnB
2018-11-19   107.00      NaN
2018-11-20   104.00      NaN
2018-11-21   106.00      NaN
2018-11-22   105.24    80.00
2018-11-23   104.63      NaN
2018-11-26   104.62      NaN
2018-11-28   104.54      NaN
2018-11-29   103.91    86.88
2018-11-30   103.43      NaN
2018-12-01   106.13      NaN
2018-12-02   110.83      NaN

预期输出:

[80, 86.88]

一些细节:

如果这个特定序列是唯一一个缺失值的序列,我可以使用For LoopsPandas - find first non-null value in column 中所述的pandas 函数first_valid_index()isnull() 来解决它,但这种情况很少发生。

我可以使用几个For Loops 来解决这个问题,但是对于较大的数据集来说速度很慢而且不是很优雅,所以我真的很想听听其他建议!

【问题讨论】:

  • 2018-11-16 的收盘价是 80.00 为什么会得到第二个值?哦。我想你是 2018-11-26 的?
  • @ScottBoston 你完全正确!我已经编辑了问题。
  • 如果你想根据Date找到最接近的非空数,那么这实际上只是一个插值问题:df.set_index('Date').ColumnB.interpolate('nearest').ffill().bfill()。如果只是基于索引的插值,则不需要.set_index

标签: python pandas


【解决方案1】:

试试这个方法,获取索引和切片获取第一个有效数字

idx= np.where(df['Date']=='2018-11-26')[0][0]
# idx 3

num = (df.loc[df.loc[:idx,'ColumnB'].first_valid_index(),'ColumnB'],
       df.loc[df.loc[idx:,'ColumnB'].first_valid_index(),'ColumnB'])

num
(80.0, 86.879999999999995)

【讨论】:

  • @ScottBoston 希望会更好。
【解决方案2】:

我会这样尝试:

import pandas as pd
import numpy as np

df_vld = df.dropna()

idx = np.argmin(abs(df_vld.index - pd.datetime(2018, 11,26)))
# 1

df_vld.loc[df_vld.index[idx]]
Out:
ColumnA    103.91
ColumnB     86.88
Name: 2018-11-29 00:00:00, dtype: float64

【讨论】:

    【解决方案3】:
    [df['ColumnB'].ffill().loc['2018-11-26'], df['ColumnB'].bfill().loc['2018-11-26']]
    

    【讨论】:

      【解决方案4】:

      您可以使用ffillbfill 来创建两列,其中包含前后的值,例如

      df['before'] = df.ColumnB.ffill()
      df['after'] = df.ColumnB.bfill()
      

      然后使用 loc 获取所需日期的值

      print (df.loc[df.Date == pd.to_datetime('2018-11-26'),['before','after']].values[0].tolist())
      [80.0, 86.88]
      

      如果您有日期列表,则可以使用isin:

      list_dates = ['2018-11-26','2018-11-28']
      print (df.loc[df.Date.isin(pd.to_datetime(list_dates)),['before','after']].values.tolist())
      [[80.0, 86.88], [80.0, 86.88]]
      

      【讨论】:

        【解决方案5】:

        这是一种方法:

        t = '2018-11-26'
        

        查找日期的索引t

        ix = df.loc[df.Date==t].index.values[0]
        

        ColumnB中保留非空值的位置:

        non_nulls = np.where(~df.ColumnB.isnull())[0]
        

        获取顶部和底部最近的非空值:

        [df.loc[non_nulls[non_nulls < ix][-1],'ColumnB']] + [df.loc[non_nulls[non_nulls > ix][0],'ColumnB']]
        
        [80.0, 86.88]
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-23
          • 2022-01-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多