本质:
如果某列包含的序列超过,比方说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
我怎样才能有效地做到这一点?
详细信息:
这是重现数据框的代码段:
# 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
...然后可能忽略从column B
到2017-01-04
的{{1}}原始缺失索引。这可能只是人们必须接受的东西。但理想情况下,解决方案应该认识到这些索引最初代表5个后续缺失值,并删除这些索引,以便生成的数据框如下所示:
2017-01-08
(但那里的最后一个NaN怎么样?那个我只是 A B
2017-01-01 -0.0053 -0.0062
2017-01-09 0.0020 0.0012
2017-01-10 NaN -0.0020
。但是对每个缺失的值做同样的事情会把事情带到远处。)
所以我猜这可能是一个比我最初怀疑的更复杂的问题(也许这就是函数fill forward
没有特定参数的原因)。
我尝试了什么:
1。 pandas.DataFrame.dropna
我认为参数pandas.DataFrame.dropna
是使用pandas.DataFrame.dropna的一种方式,但根据文档,该参数设置了现有的阈值,而不是缺失值:
thresh:int,默认无
int value:要求许多非NA值
2。按列定义和查找纳米柱的图案
以下是基于建议答案here的可能解决方案。但是,它确实要求您定义您正在查找序列中的5个且仅缺少5个变量。为了完成解决方案,我还必须找到所有列表中的索引联合,这些列表表示所有列的缺失序列的索引,然后将数据帧的子集编入其中。
感谢您提出任何其他建议!
这是一个简单的复制粘贴的全部内容:
thresh
输出(逐列纳米序列的索引):
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)
答案 0 :(得分:2)
这应该为你解决。它不会删除行直到结束,因此它将在第二个场景中正确地解析多个列。我已经使用了并发症部分的df
来输出以下代码。
说明:
我们创建了另一个df,其中NaN
值被赋值为零,每个有限值都被赋值为1(如果您的初始df
值为零,则需要先将它们映射到此虚拟df2
中的任何其他数字,然后是.fillna(0).astype('bool')
)
按每列累积总和进行分组,可以查找连续NaN
个值超过5个的位置。与原始df的比较确保我们不会捕获第一个非空值。
对于应该删除的任何行,最后会创建掩码,因此您可以针对多个NaN
值重叠的列正确解析它。
以下是代码:
import pandas as pd
import numpy as np
## If the initial df contains values of 0 do this instead of the first line below
#df2 = df.copy()
#df2[df2==0] = 0.01
#df2 = df2.fillna(0).astype('bool').cumsum()
# Min number of consecutive NaN values to begin dropping
n_cons = 5
df2 = df.fillna(0).astype('bool').cumsum()
for col in df2.columns:
df2[col] = df2.groupby(col)[col].transform(lambda x: np.size(x) > n_cons)
df2[col] = df2[col] & df[col].isnull()
mask = df2.any(axis=1)
df[~mask]
# A B
#2017-01-01 -0.0053 -0.0062
#2017-01-09 0.0020 0.0012
#2017-01-10 NaN -0.0020