【发布时间】:2018-04-27 13:00:23
【问题描述】:
本质:
如果一列包含超过 5 个缺失值的序列,我想从该数据框中删除相应的索引。所以在像下面这样的数据框中......
A B
2017-01-01 -0.0053 -0.0062
2017-01-02 NaN 0.0016
2017-01-03 NaN 0.0043
2017-01-04 NaN -0.0077
2017-01-05 NaN -0.0070
2017-01-06 NaN 0.0058
2017-01-07 0.0024 -0.0074
2017-01-08 0.0018 0.0086
2017-01-09 0.0020 0.0012
2017-01-10 -0.0031 -0.0020
2017-01-11 0.0027 NaN
2017-01-12 -0.0050 NaN
2017-01-13 -0.0063 NaN
2017-01-14 0.0066 0.0095
2017-01-15 0.0039 0.0028
...我想删除索引 2017-01-02 到 2017-01-06 以便所需的输出如下所示:
A B
2017-01-01 -0.0053 -0.0062
2017-01-07 0.0024 -0.0074
2017-01-08 0.0018 0.0086
2017-01-09 0.0020 0.0012
2017-01-10 -0.0031 -0.0020
2017-01-11 0.0027 NaN
2017-01-12 -0.0050 NaN
2017-01-13 -0.0063 NaN
2017-01-14 0.0066 0.0095
2017-01-15 0.0039 0.0028
我怎样才能有效地做到这一点?
详情:
这是一个重现数据帧的 sn-p:
# imports
import pandas as pd
import numpy as np
np.random.seed(1234)
# Reproducible data sample
def df_sample(rows, names):
''' Function to create data sample with random returns
Parameters
==========
rows : number of rows in the dataframe
names: list of names to represent assets
Example
=======
>>> returns(rows = 2, names = ['A', 'B'])
A B
2017-01-01 0.0027 0.0075
2017-01-02 -0.0050 -0.0024
'''
listVars= names
rng = pd.date_range('1/1/2017', periods=rows, freq='D')
df_temp = pd.DataFrame(np.random.randint(-100,100,size=(rows, len(listVars))), columns=listVars)
df_temp = df_temp.set_index(rng)
df_temp = df_temp / 10000
return df_temp
df = df_sample(15,list('AB'))
我知道的并发症
如果数据框在多个列中有重叠索引且缺失值,如下所示:
A B
2017-01-01 -0.0053 -0.0062
2017-01-02 NaN 0.0016
2017-01-03 NaN 0.0043
2017-01-04 NaN NaN
2017-01-05 NaN NaN
2017-01-06 NaN NaN
2017-01-07 0.0024 NaN
2017-01-08 0.0018 NaN
2017-01-09 0.0020 0.0012
2017-01-10 NaN -0.0020
...那么我猜任何使用apply 的解决方案都会逐列呈现一个像这样的临时数据框...
A B
2017-01-01 -0.0053 -0.0062
2017-01-07 0.0024 NaN
2017-01-08 0.0018 NaN
2017-01-09 0.0020 0.0012
2017-01-10 NaN -0.0020
...然后可能会忽略从2017-01-04 到2017-01-08 的column B 的原始缺失索引。不过,这也许只是人们不得不接受的事情。但理想情况下,解决方案应该认识到这些索引最初代表 5 个连续缺失的值,并删除这些索引,以便生成的数据框如下所示:
A B
2017-01-01 -0.0053 -0.0062
2017-01-09 0.0020 0.0012
2017-01-10 NaN -0.0020
(但是那里的最后一个 NaN 呢?那个我会简单地 fill forward。但是对 每个 缺失值做同样的事情会让事情变得很远。)
所以我想这可能是一个比我最初怀疑的要复杂得多的问题(也许这也是函数 pandas.DataFrame.dropna 没有具体参数的原因)。
我尝试过的:
1. pandas.DataFrame.dropna
我认为参数 thresh 将是使用 pandas.DataFrame.dropna 的一种方式,但根据文档,该参数为 existing 而不是 missing 设置阈值价值观:
thresh : int,默认无
int value : 需要很多非 NA 值
2。逐列定义和查找nan的模式
以下是基于建议答案here 的可能解决方案。但是,它确实需要您定义要在序列中查找 5 个且仅 5 个缺失值。为了完成这个解决方案,我还必须在所有列表中找到索引的联合,这些列表代表所有列的缺失序列的索引,然后根据它对数据框进行子集化。
感谢您的任何其他建议!
这是一个简单的复制粘贴的全部内容:
import pandas as pd
import numpy as np
np.random.seed(1234)
# Reproducible data sample
def df_sample(rows, names):
''' Function to create data sample with random returns
Parameters
==========
rows : number of rows in the dataframe
names: list of names to represent assets
Example
=======
>>> returns(rows = 2, names = ['A', 'B'])
A B
2017-01-01 0.0027 0.0075
2017-01-02 -0.0050 -0.0024
'''
listVars= names
rng = pd.date_range('1/1/2017', periods=rows, freq='D')
df_temp = pd.DataFrame(np.random.randint(-100,100,size=(rows, len(listVars))), columns=listVars)
df_temp = df_temp.set_index(rng)
df_temp = df_temp / 10000
return df_temp
df = df_sample(15,list('AB'))
df['A'][1:6] = np.nan
df['B'][3:8] = np.nan
dfi = df
# convert to boolean values
df = dfi
df = df.isnull()
# specify pattern
pattern = [True,True, True, True, True]
# prepare for a for loop
idx = []
# loop through all columns and identify sequence of missing values
for col in df:
df_temp = df[col].to_frame()
matched = df_temp.rolling(len(pattern)).apply(lambda x: all(np.equal(x, pattern)))
matched = matched.sum(axis = 1).astype(bool)
idx_matched = np.where(matched)[0]
subset = [range(match-len(pattern)+1, match+1) for match in idx_matched]
result = pd.concat([df.iloc[subs,:] for subs in subset], axis = 0).index
idx.append(result)
print(idx)
输出(按列索引 nan 序列):
[DatetimeIndex(['2017-01-02', '2017-01-03', '2017-01-04', '2017-01-05','2017-01-06'],
dtype='datetime64[ns]', freq=None),
DatetimeIndex(['2017-01-04', '2017-01-05', '2017-01-06', '2017-01-07', '2017-01-08'],
dtype='datetime64[ns]', freq=None)]
【问题讨论】:
-
您的索引是否总是相隔 1 天的日期时间?有一种方法可以在日期时间索引上使用闭包和过滤器来执行滑动窗口操作。
-
不,一点也不。事实上,周末总是会像其他工作日一样随机缺失。
标签: python pandas missing-data