如何仅在使用熊猫的值(在列中的最后一个 NaN 之前和之后停止)之间进行插值?

ver*_*era 4 python interpolation pandas

如果我有一个df类似的:

print(df)
                       A  B  C    D    E
 DATE_TIME                               
2016-08-10 13:57:00  3.6  A  1  NaN  NaN
2016-08-10 13:58:00  4.7  A  1  4.5  NaN
2016-08-10 13:59:00  3.4  A  0  NaN  5.7
2016-08-10 14:00:00  3.5  A  0  NaN  NaN
2016-08-10 14:01:00  2.6  A  0  4.6  NaN
2016-08-10 14:02:00  4.8  A  0  NaN  4.3
2016-08-10 14:03:00  5.7  A  1  NaN  NaN
2016-08-10 14:04:00  5.5  A  1  5.7  NaN
2016-08-10 14:05:00  5.6  A  1  NaN  NaN
2016-08-10 14:06:00  7.8  A  1  NaN  5.2
2016-08-10 14:07:00  8.9  A  0  NaN  NaN
2016-08-10 14:08:00  3.6  A  0  NaN  NaN

print (df.dtypes)
A    float64
B     object
C      int64
D    float64
E    float64
dtype: object
Run Code Online (Sandbox Code Playgroud)

感谢来自社区的大量输入,我现在有了这个代码,它允许我将我的 df 上采样到第二个间隔,将不同的方法应用于不同的 dtypes

int_cols = df.select_dtypes(['int64']).columns
index = pd.date_range(df.index[0], df.index[-1], freq="s")
df2 = df.reindex(index)

for col in df2:
if col == int_cols.all(): 
    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)
Run Code Online (Sandbox Code Playgroud)

我现在正在寻找一种方法,仅在我的实际测量值之间进行插值。插值函数将我的最后一次测量扩展到df:

 df2.tail()
Out[75]: 
                            A  B  C    D    E
2016-08-10 14:07:56  3.953333  A  0  5.7  5.2
2016-08-10 14:07:57  3.865000  A  0  5.7  5.2
2016-08-10 14:07:58  3.776667  A  0  5.7  5.2
2016-08-10 14:07:59  3.688333  A  0  5.7  5.2
2016-08-10 14:08:00  3.600000  A  0  5.7  5.2
Run Code Online (Sandbox Code Playgroud)

但是我想在最后一次测量发生时停止(例如在 14:04:00col['D']和 14:06:00 col['D'])并离开 NaN。

它尝试将“limit”和“limit_direction”的零值添加到“both”:

 for col in df2:
if col == int_cols.all(): 
    df2[col].ffill(inplace=True)
    df2[col] = df2[col].astype(int)
elif df2[col].dtype == float:
    df2[col].interpolate(inplace=True,limit=0, limit_direction='both')
else:
    df2[col].ffill(inplace=True)
Run Code Online (Sandbox Code Playgroud)

但这对输出没有任何改变。我然后尝试将我找到的解决方案合并到这个问题中:Pandas:插值,其中列中的第一个和最后一个数据点是 NaN到我的代码中:

for col in df2:
if col == int_cols.all(): 
    df2[col].ffill(inplace=True)
    df2[col] = df2[col].astype(int)
elif df2[col].dtype == float:
   df2[col].loc[df2[col].first_valid_index(): df2[col].last_valid_index()]=df2[col].loc[df2[col].first_valid_index(): df2[col].last_valid_index()].astype(float).interpolate(inplace=True)
else:
    df2[col].ffill(inplace=True)
Run Code Online (Sandbox Code Playgroud)

...但这不起作用,我的float64列现在纯粹是 NaN...此外,我尝试插入代码的方式,我知道它只会影响float列。在理想的解决方案中,我希望将此first_valid_index():.last_valid_index()选择也设置为object和int64列。有人可以帮助我吗?..谢谢你

jez*_*ael 5

对于大熊猫0.23.0可以使用参数limit_area在interpolate:

df = pd.DataFrame({'A': [np.nan, 1.0, np.nan, np.nan, 4.0, np.nan, np.nan],
                   'B': [np.nan, np.nan, 0.0, np.nan, np.nan, 2.0, np.nan]},
                  columns=['A', 'B'], 
                  index=pd.date_range(start='2016-08-10 13:50:00', periods=7, freq='S'))
print (df)
                       A    B
2016-08-10 13:50:00  NaN  NaN
2016-08-10 13:50:01  1.0  NaN
2016-08-10 13:50:02  NaN  0.0
2016-08-10 13:50:03  NaN  NaN
2016-08-10 13:50:04  4.0  NaN
2016-08-10 13:50:05  NaN  2.0
2016-08-10 13:50:06  NaN  NaN

df = df.interpolate(limit_direction='both', limit_area='inside')
print (df)
                       A         B
2016-08-10 13:50:00  NaN       NaN
2016-08-10 13:50:01  1.0       NaN
2016-08-10 13:50:02  2.0  0.000000
2016-08-10 13:50:03  3.0  0.666667
2016-08-10 13:50:04  4.0  1.333333
2016-08-10 13:50:05  NaN  2.000000
2016-08-10 13:50:06  NaN       NaN
Run Code Online (Sandbox Code Playgroud)


Mar*_*ese 2

你们非常接近!这是一个说明要点的示例,该示例与您在帖子末尾发布的代码非常相似:

import numpy as np
import pandas as pd

df = pd.DataFrame({'A': [np.nan, 1.0, np.nan, np.nan, 4.0, np.nan, np.nan],
                   'B': [np.nan, np.nan, 0.0, np.nan, np.nan, 2.0, np.nan]},
                  columns=['A', 'B'], 
                  index=pd.date_range(start='2016-08-10 13:50:00', periods=7, freq='S'))
print df

A_first = df['A'].first_valid_index()
A_last = df['A'].last_valid_index()
df.loc[A_first:A_last, 'A'] = df.loc[A_first:A_last, 'A'].interpolate()

B_first = df['B'].first_valid_index()
B_last = df['B'].last_valid_index()
df.loc[B_first:B_last, 'B'] = df.loc[B_first:B_last, 'B'].interpolate()

print df
Run Code Online (Sandbox Code Playgroud)

结果:

                       A    B
2016-08-10 13:50:00  NaN  NaN
2016-08-10 13:50:01  1.0  NaN
2016-08-10 13:50:02  NaN  0.0
2016-08-10 13:50:03  NaN  NaN
2016-08-10 13:50:04  4.0  NaN
2016-08-10 13:50:05  NaN  2.0
2016-08-10 13:50:06  NaN  NaN

                       A         B
2016-08-10 13:50:00  NaN       NaN
2016-08-10 13:50:01  1.0       NaN
2016-08-10 13:50:02  2.0  0.000000
2016-08-10 13:50:03  3.0  0.666667
2016-08-10 13:50:04  4.0  1.333333
2016-08-10 13:50:05  NaN  2.000000
2016-08-10 13:50:06  NaN       NaN
Run Code Online (Sandbox Code Playgroud)

您的代码中的两个问题是:

  1. 如果您打算这样做df[...] = df[...].interpolate(),则需要将其删除,inplace=True因为这会使其返回None。这是你的主要问题,也是你得到一切的原因NaNs。
  2. 虽然它在这里似乎可行,但总的来说,链式索引是不好的:

你要:

df.loc[A_first:A_last, 'A'] = df.loc[A_first:A_last, 'A'].interpolate()
Run Code Online (Sandbox Code Playgroud)

不是:

df['A'].loc[A_first:A_last] = df['A'].loc[A_first:A_last].interpolate()
Run Code Online (Sandbox Code Playgroud)

有关更多详细信息,请参阅此处:http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy