Python B按间隔填充以更正丢失/无效条目

Python B按间隔填充以更正丢失/无效条目,python,pandas,numpy,Python,Pandas,Numpy,所以我有一个数据帧 df = pandas.DataFrame([[numpy.nan,5],[numpy.nan,5],[2015,5],[2020,5],[numpy.nan,10],[numpy.nan,10],[numpy.nan,10],[2090,10],[2100,10]],columns=["value","interval"]) value interval 0 NaN 5 1 NaN 5 2 2015.0

所以我有一个数据帧

df = pandas.DataFrame([[numpy.nan,5],[numpy.nan,5],[2015,5],[2020,5],[numpy.nan,10],[numpy.nan,10],[numpy.nan,10],[2090,10],[2100,10]],columns=["value","interval"])

    value  interval
0     NaN         5
1     NaN         5
2  2015.0         5
3  2020.0         5
4     NaN        10
5     NaN        10
6     NaN        10
7  2090.0        10
8  2100.0        10
我需要根据NaN值的间隔和该索引后的第一个非NaN值向后填充NaN值,以便得到预期的输出

    value  interval
0  2005.0         5  # corrected 2010 - 5(interval)
1  2010.0         5  # corrected 2015 - 5(interval)
2  2015.0         5  # no change ( use this to correct 2 previous rows)
3  2020.0         5  # no change
4  2060.0        10  # corrected 2070 - 10
5  2070.0        10  # corrected 2080 - 10 
6  2080.0        10  # corrected 2090 - 10 
7  2090.0        10  # no change (use this to correct 3 previous rows)
8  2100.0        10  # no change
我不知道如何使用pandas/numpy矢量化操作来完成这项任务

我可以用一个非常简单的循环来完成

last_good_value = None
fixed_values = []
for val,interval in reversed(df.values):
    if val == numpy.nan and last_good_value is not None:
       fixed_values.append(last_good_value - interval)
       last_good_value = fixed_values[-1]
    else:
       fixed_values.append(val) 
       if val != numpy.nan:
           last_good_value = val

print (reversed(fixed_values))

严格地说,这是有效的。。。但是我想了解一个pandas解决方案,它可以解析值,避免循环(实际上这是一个很大的列表)

创建一个分组序列,通过使用
[:-1]
反转,将最后一个非空值与前面的所有
NaN
行分组。然后,您可以
b填充
并使用
cumsum
确定每行减去多少

s = df['value'].notnull()[::-1].cumsum()
subt = df.loc[df['value'].isnull(), 'interval'][::-1].groupby(s).cumsum()

df['value'] = df.groupby(s)['value'].bfill().subtract(subt, fill_value=0)


由于
subt
仅是NaN行的子集,因此
fill_值=0
确保具有值的行保持不变

print(subt)
#6    10
#5    20
#4    30
#1     5
#0    10
#Name: interval, dtype: int64

创建一个分组系列,通过使用
[::-1]
反转,将最后一个非空值与其前面的所有
NaN
行进行分组。然后,您可以
b填充
并使用
cumsum
确定每行减去多少

s = df['value'].notnull()[::-1].cumsum()
subt = df.loc[df['value'].isnull(), 'interval'][::-1].groupby(s).cumsum()

df['value'] = df.groupby(s)['value'].bfill().subtract(subt, fill_value=0)


由于
subt
仅是NaN行的子集,因此
fill_值=0
确保具有值的行保持不变

print(subt)
#6    10
#5    20
#4    30
#1     5
#0    10
#Name: interval, dtype: int64

首先,获取组中共享相同“间隔”值的行的位置。
然后,获取每组的最后一个值。
您要查找的是“最后一个值-位置*间隔”


首先,获取组中共享相同“间隔”值的行的位置。
然后,获取每组的最后一个值。
您要查找的是“最后一个值-位置*间隔”



缺少的值总是在组中排在第一位吗,或者您需要填充后面的行吗?嘿,谢谢您的提问,不,它们总是从正确的值向后填充(也可能有数百个无效值的条纹,不像示例中的2或3)间隔值总是连续的吗?或者在10之后可能有另一个间隔5?是的,数据集中稍后可能会有一个间隔5:/n缺少的值总是在组中的第一位,还是需要填充后面的行?嘿,谢谢你的提问,不,它们总是从正确的值向后填充(也可能有成百上千的无效值,而不仅仅是示例中的2或3)间隔值总是连续的吗?或者在10之后可能有另一个间隔5?是的,数据集中稍后可能有一个间隔5:/这看起来很有希望,这对我来说也是非常可读的:)因此,非常感谢这一点。。。我可能不得不改变到另一个答案作为接受(它可能更快?),但这仍然是一个伟大的答案谢谢!另一个答案是更快。。。不过这本书对我来说更具可读性。。。但这项工作的速度对我来说至关重要,所以我改变了计划answer@JoranBeasley有道理。我假设groupby操作的优化程度有所不同
bfill
从来没有让我觉得它特别快,而且
rank
first
我认为它们的路径很快。对不起,我可能把bfill列为我的目标而把它搞砸了:/这看起来很有希望,对我来说也很容易理解:)所以非常感谢您的帮助。。。我可能不得不改变到另一个答案作为接受(它可能更快?),但这仍然是一个伟大的答案谢谢!另一个答案是更快。。。不过这本书对我来说更具可读性。。。但这项工作的速度对我来说至关重要,所以我改变了计划answer@JoranBeasley有道理。我假设groupby操作的优化程度有所不同
bfill
从来没有让我觉得它特别快,而且
rank
first
我认为它们的路径很快。抱歉,我可能把bfill列为我的目标而搞砸了:/这看起来也很棒(虽然对我来说有点神秘)。。。而且它看起来稍微快一点。。。我会介绍更多,如果更快,我可能会将此更改为公认的答案:)抱歉,如果不够清楚。我只是想,要在“值”列中获取所需的数据,只需查看它所在的“间隔”组。您可以找到此组中的最后一个“值”。然后将“interval”值减去N次,N是组内的行位置。希望这个解释有帮助。是的,它确实。。。我只是盯着它看了很久:P回答得很好,非常感谢。。。正是我需要的输出:)这看起来也很棒(虽然对我来说有点神秘)。。。而且它看起来稍微快一点。。。我会介绍更多,如果更快,我可能会将此更改为公认的答案:)抱歉,如果不够清楚。我只是想,要在“值”列中获取所需的数据,只需查看它所在的“间隔”组。您可以找到此组中的最后一个“值”。然后将“interval”值减去N次,N是组内的行位置。希望这个解释有帮助。是的,它确实。。。我只是盯着它看了很久:P回答得很好,非常感谢。。。正是我需要的输出:)