Pandas系列行包含NaN的乘法

3

给定这个数据框:

import pandas as pd
import numpy as np

data = {'column1': [True,False, False, True, True],
        'column2' : [np.nan,0.21, np.nan, 0.2222, np.nan],
        'column3': [1000, 0, 0, 0, 0 ]}


df = pd.DataFrame.from_dict(data)

print(df)

   column1  column2  column3
0     True      NaN     1000
1    False   0.2100        0
2    False      NaN        0
3     True   0.2222        0
4     True      NaN        0

column2行不是NaN时,如何将结果与column3的上一个值相乘?否则只返回column3的上一个值?

结果应该像这样:

   column1  column2  column3
0     True      NaN     1000
1    False   0.2100        210
2    False      NaN        210
3     True   0.2222        46.662
4     True      NaN        46.662

我一直在浏览类似的问题,但是我就是想不明白...

我很感谢您的帮助 :)


https://dev59.com/92Ag5IYBdhLWcg3wq8aU - Hielke Walinga
你能否发布一下你尝试过的内容,以及可能没有成功的部分?你理解(或更喜欢)列表推导式吗?column1对输出有任何影响吗? - rajah9
@rajah9 Column1对输出没有影响,我一直在尝试使用np.where(np.isnan('column2')等等创建Column3。但是我一无所获,不确定这是否是正确的策略。 - Finger twist
4个回答

2
你可以尝试这个方法:

最初的回答:

#replace 0 with nan and create a copy of the df
m=df.assign(column3=df.column3.replace(0,np.nan))
#ffill on axis 1 where column2 is not null , and filter the last col then cumprod
final=(df.assign(column3=m.mask(m.column2.notna(),m.ffill(1)).iloc[:,-1].cumprod().ffill()))

   column1  column2   column3
0     True      NaN  1000.000
1    False   0.2100   210.000
2    False      NaN   210.000
3     True   0.2222    46.662
4     True      NaN    46.662

1
使用 isnull().at

Ex.

import pandas as pd
import numpy as np

data = {'column1': [True,False, False, True, True],
        'column2' : [np.nan,0.21, np.nan, 0.2222, np.nan],
        'column3': [1000, 0, 0, 0, 0 ]}
df = pd.DataFrame.from_dict(data)
pre_idx = 0
for idx in df.index:
    is_nan = pd.isnull(df['column2'][idx])
    if idx != 0:
        pre_idx = idx -1
    df.at[idx, 'column3'] = df.at[pre_idx, 'column3'] * (1 if is_nan else df.at[idx, 'column2'])
print(df)

输出:
   column1  column2  column3
0     True      NaN     1000
1    False   0.2100      210
2    False      NaN      210
3     True   0.2222       46
4     True      NaN       46

1

我会定义一个虚拟类来累加column3的最后一个值,然后迭代行进行计算。如果你这样做,就可以避免编写for循环,并将计算集中在map调用中,例如可以轻松并行运行。

class AccumMult:
    def __init__(self):
        self.last_val = None

    def mult(self, c2, c3):
        self.last_val = c3 if self.last_val is None else self.last_val
        if not np.isnan(c2):
            self.last_val = self.last_val * c2
        return self.last_val

m = AccumMult()

df["column3"] = list(map(lambda x: m.mult(x[0], x[1]), df[["column2", "column3"]].values.tolist()))

0
由于第x行的值取决于它之前所有行的信息,我猜你别无选择,需要迭代每一行。你可以这样做:
prev = df.at[0, 'column3']
for e, row in df.iterrows():
    prev = df.at[e, 'column3'] = prev * (1 if np.isnan(row.column2) else row.column2)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接