如何使用多个行和多个列作为输入在DataFrame列上应用函数?

时间:2019-06-18 21:20:47

标签: python pandas

我有一系列事件,根据一些变量(先前的命令,先前/当前代码以及先前/当前状态),我需要确定与该事件相关的命令。

我实际上有一个可以按预期工作的代码,但是有点慢。因此,我尝试使用df.apply,但我认为不可能使用比当前元素更多的内容作为输入。 (代码从1开始,因为第一行始终是“开始”命令)

def mark_commands(df):
    for i in range(1, len(df)):
        prev_command = df.loc[i-1, 'Command']
        prev_code, cur_code = df.loc[i-1, 'Code'], df.loc[i, 'Code']
        prev_status, cur_status = df.loc[i-1, 'Status'], df.loc[i, 'Status']

        if (prev_command == "end" and 
            ((cur_code == 810 and cur_status in [10, 15]) or 
            (cur_code == 830 and cur_status == 15))):

            df.loc[i, 'Command'] = "ignore"

        elif ((cur_code == 800 and cur_status in [20, 25]) or 
            (cur_code in [810, 830] and cur_status in [10, 15])):

            df.loc[i, 'Command'] = "end"

        elif ((prev_code != 800) and 
            ((cur_code == 820 and cur_status == 25) or 
            (cur_code == 820 and cur_status == 20 and 
                prev_code in [810, 820] and prev_status == 20) or 
            (cur_code == 830 and cur_status == 25 and 
                prev_code == 820 and prev_status == 20))):

            df.loc[i, 'Command'] = "continue"

        else:

            df.loc[i, 'Command'] = "begin"

    return df

这是一个正确标记的CSV格式示例(可以用作输入,因为唯一的区别是命令行中的所有内容在首次开始后都是空的):

Code,Status,Command
810,20,begin
810,10,end
810,25,begin
810,15,end
810,15,ignore
810,20,begin
810,10,end
810,25,begin
810,15,end
810,15,ignore
810,20,begin
800,20,end
810,10,ignore
810,25,begin
820,25,continue
820,25,continue
820,25,continue
820,25,continue
800,25,end

1 个答案:

答案 0 :(得分:0)

您的代码基本上是完美的(您本可以使用for,如果您的索引不是线性的,则在df.apply循环中会更安全,但不会改变速度)。 / p>

广泛尝试使用"Command"之后,我意识到自从df列不断从一行更新到另一行以来,流程是致命的。由于df['Command'] = df.apply(lambda row: mark_commands(row), axis=1) 是“静态”的,因此以下操作无效:

continue

最终,为了节省您的计算量,如果您的ifelif语句直接进入下一个迭代,则每次满足条件时都可以插入一个if (prev_command == "end" and ....) : df.loc[i, 'Command'] = "ignore" continue 语句:< / p>

    import express from "express";

    import { HomeController } from "./controllers";

    const app: express.Application = express();
    const port: number = ((process.env.PORT as any) as number) || 3000;

    app.use(express.static("static"));

    app.use("/", HomeController);

    app.listen(port, () => {
      // tslint:disable-next-line:no-console
      console.log(`Listening at http://localhost:${port}/`);
    });

话虽如此,您的代码效果很好。