我现在正在处理的代码有问题,所以基本上我得到的是一个数据帧,其中有一列用pd形式的数字填充。例如,数据帧([2,2,2,0,0,0,0,2,0,2](。所以我想要的输出是[2,2,2,0,0,0,10,0,4](就像记忆效果(。
所以我在想,如果有一种方法可以做这样的事情:
df.apply(lambda x: x * (index(x) - index( lastnotnull(x) ) ) if x!=0 else 0, axis=1)
任何想法都可以,但最好是优化的。
lastnotnull并不是一个真正的函数,它只是解释我想法的一种方式。所以基本上,我想要的是,在每一行中,它检查它是否为null,如果它是0,否则它将它乘以(以前的null值的数量+1(,所以在我的例子中,第四个2变成2*(7-"2"(=10,7是2的索引,变为10;2〃;是列表中第三个2的索引,它是列表的最后一个非空值。
您在文章中包含了一个如何计算预期值:(2 * (7 - 2) = 10
(。这表明一个更精确的公式,对于值!=0,更确切地说是:
x * (index(x) - index(previousNonZero(x)))
注意以下差异:
- lastnotnull(如您所写(表示当前列,而不管当前元素是什么。如果此列不包含NaN,则这是最后行中的元素
- previousNonZero(一个更精确的公式(表示您从当前元素向上查找元素就是!=0。您没有指定如何处理第一行,其中没有前一行,所以我假设这种情况将是0(与第一行相同(
为了有一些列名,而不是默认的0,我创建了源DataFrame为:
df = pd.DataFrame({'x': [2, 2, 2, 0, 0, 0, 0, 2, 0, 2]})
从而将该列命名为x。
为了容易地找到先前的非零元素(及其索引(,让我们创建一个辅助DataFrame:
wrk = df[df.x != 0]
要生成预期结果,请运行:
result = np.where(df.x != 0, df.x * (wrk.index - wrk.index.to_series()
.shift(fill_value=0)), 0).astype(int)
详细信息:
df.x != 0
-条件参数到np。其中wrk.index.to_series().shift(fill_value=0)
-x列中的前一个非零元素(替换了初始NaN0(df.x * (wrk.index - ...)
-x!=的公式0情况下0
-x==0情况下的公式astype(int)
-将结果转换为int(否则为float(
结果是:
array([ 0, 2, 2, 0, 0, 0, 0, 10, 0, 4])
请注意,第一个元素与您的预期结果不同,但这是所用公式的结果。
为了支持我的观点,让我们分析第一行的情况:
- CCD_ 7=2
- CCD_ 8==0
- CCD_ 9==0
- CCD_ 10==0
- 最终结果==0
一种替代方案:将fill_value更改为-1("假设";前一行(如果存在((,结果将如您所愿。
编辑
上面的代码可以重新编写成一个函数,对任何列进行操作源DataFrame:
def proc(col):
wrk = col[col != 0]
return (col * (wrk.index - wrk.index.to_series()
.shift(fill_value=-1))).fillna(0, downcast='infer')
在该函数中,仍然会创建一个临时系列(wrk(,但是退出该函数后,它将被垃圾收集,所以不用担心关于这个细节。
现在你可以称之为:
result = proc(df.x)
获取(这次是系列(:
0 2
1 2
2 2
3 0
4 0
5 0
6 0
7 10
8 0
9 4
dtype: int64
左列是索引和右值(以前在数组中(。
如果需要,请将此函数的名称更改为您选择的任何其他名称(我没有更好的主意(。