如何在应用功能熊猫中更改数据框

时间:2019-06-13 12:46:43

标签: pandas apply

我要使用Apply来动态修改我的数据框的内容,该表就像:

Client.shared.reactions(forActivityId: state.activity.id, extraDataTypeOf: ReactionExtraData.self, userTypeOf: User.self) { [weak self](result) in
        DispatchQueue.main.async {
            self.state.connectionStatus = .ready
            if let value = try? result.get() {
                TempLogger.log("\(value.reactions.count)")
            }
        }
    }

我的代码是:

   index  price signal  stoploss
0      0   1000   True     990.0
1      1   1010  False     990.0
2      2   1020   True    1010.0
3      3   1000  False    1010.0
4      4    990  False    1010.0
5      5    980  False    1010.0
6      6   1000  False    1010.0
7      7   1020   True    1010.0
8      8   1030  False    1010.0
9      9   1040  False    1010.0

当我进入功能测试时,可以看到该值确实更改为1,但是超出功能测试范围,似乎对数据框没有影响。

我尝试使用另一种方式来修改数据框的内容,

def test(row, dd):
    if row.signal:
        dd['inorder']=True
        row['stoploss']=1

    df = pd.DataFrame({'index':[0,1,2,3,4,5,6,7,8,9],
                   'price':[1000,1010,1020,1000,990,980,1000,1020,1030,1040],
                   'signal':[True, False, True, False, False, False, False, True, False, False]})


if __name__ == '__main__':
    df['stoploss'] = df.loc[df['signal'], 'price'] - 10
    df['stoploss'].ffill(inplace=True)


    xx = dict(inorder=False)
    df.apply(lambda row: test(row, xx), axis=1)
    print(df)

这是可行的,但是显然比应用慢得多。

我期望的正确结果是:

for k, row in df.iterrows():
    if row.signal:
        xx['inorder'] = True
        df.loc[k, 'stoploss'] = 1

请问如何在申请中完成该任务?

谢谢

1 个答案:

答案 0 :(得分:0)

如果查看apply的文档,您会注意到apply不会更改DataFrame的位置,而是返回已应用该功能的新数据框。

因此,在几秒钟到最后一行,您可以尝试

df = df.apply(lambda row: test(row, xx), axis=1)

编辑:

IMO,这没有很好的记录,但是电话 df.apply(func, axis=1)func应用于每一行,并将行设置为返回值func

按照书面规定,您的示例将无法运行,因为您正在应用的函数不会返回任何内容。以下最小示例按照您的预期方式工作。

df = pd.DataFrame({'index':[0,1,2,3,4,5,6,7,8,9],
                   'price':[1000,1010,1020,1000,990,980,1000,1020,1030,1040],
                   'signal':[True, False, True, False, False, False, False, True, False, False]})

df['stoploss'] = df.loc[df['signal'], 'price'] - 10
df['stoploss'].ffill(inplace=True)

def test(row):
    row.stoploss = 1 if row.signal else row.stoploss
    return row

modified_df = df.apply(test, axis=1)

顺便说一句,我认为您实际上并不需要使用apply来获得所需的结果。您是否尝试过类似的

df.loc[df['signal'] == True, 'stoploss'] = 1

这将是获得目标输出的更简单,更快捷的方法。