从数据帧中切片和提取

Slicing and extracting from dataframe

提问人:Karma_X 提问时间:8/23/2023 最后编辑:Karma_X 更新时间:8/23/2023 访问量:66

问:

我有一个如下的数据帧:

     time  power speed state 

1   14.00  29    3     1
2   14.01  30    3     2
3   14.02  29    3     3
4   14.03  30    3     4
5   14.04  29    3     5
6   14.05  30    3     6
7   14.06  29    3     6
8   14.07  30    3     6
9   14.08  29    3     6
10  14.09  30    3     5
11  14.10  29    3     5
12  14.11  30    3     5
13  14.12  29    3     5
14  14.13  30    3     6
15  14.14  31    4     6 
16  14.15  32    4     6

每个循环从状态 5(第 10 行,仅在状态 6 之后)开始,并在状态 6 返回之前结束(即第 13 行)。因此,循环 1 在第 10 行和第 13 行之间。

这是一个大数据,有多个周期。我想将每个周期提取为数据帧。 我尝试了一些迭代,但没有奏效。

 charge_cycles = []
current_charge_start = None
current_drive_start = None
total_energy_consumed = 0
drive_data = []

for index, row in data.iterrows():
    if row['state'] == '6':
        if current_drive_start is not None:
            energy_during_drive = total_energy_consumed
            charge_cycles.append(energy_during_drive)
            drive_data.append(data.loc[current_drive_start:index])
            current_drive_start = None
            total_energy_consumed = 0
        current_charge_start = row['time']
    elif row['state'] == '5':
        if current_charge_start is not None and current_drive_start is None:
            current_drive_start = index
        if current_drive_start is not None:
            total_energy_consumed += row['power'] * (row['time'] - data.loc[current_drive_start, 'time'])
            current_drive_start = index

# Print the energy consumption during driving between each charge cycle
for i, energy in enumerate(charge_cycles, start=1):
    print(f"Charge Cycle {i}: Energy Consumed During Driving = {energy} units")

# Display the DataFrames for each driving cycle
for i, drive_df in enumerate(drive_data, start=1):
    print(f"Driving Cycle {i}:\n{drive_df}")

结果,这给了我整个数据框。任何人都可以帮我解决这个问题的python代码吗?

Python Pandas 数据帧 切片

评论

0赞 RomanPerekhrest 8/23/2023
发布您的最小编码尝试
0赞 C.Nivs 8/23/2023
那么只有当状态 5 绑定在 6 之间时?其他 6 会怎样?您能给我们提供示例输出并扩展一下您的测试集吗?我们忽略 1-4 吗?
0赞 Karma_X 8/23/2023
@C.Nivs 通常它绑定在 6 之间。其他 6 代表一个新的周期。对于前6666665555555555555543555555512555666666666666666655555555412344666666666
0赞 RomanPerekhrest 8/23/2023
@Karma_X,在您之前的评论中,您展示了一个具有 2 个周期的示例,对吗?
0赞 Karma_X 8/23/2023
@RomanPerekhrest 是的,你是对的。

答:

2赞 mozway 8/23/2023 #1

您可以尝试使用布尔索引和 .groupby

如果只想在状态 6 之后启动的组,请添加一些筛选。

m1 = df['state'].eq(5)
m2 = df['state'].eq(6)
m3 = m2.mask(m1).ffill()

dfs = [g for k,g in df[m1&m3].groupby(m2.cumsum())]

或两个状态之间 6:

m1 = df['state'].eq(5)
m2 = df['state'].eq(6)
m3 = m2.mask(m1).ffill() & m2.mask(m1).bfill()

dfs = [g for k,g in df[m1&m3].groupby(m2.cumsum())]

数据帧的输出列表:

[     time  power  speed  state
10  14.09     30      3      5
11  14.10     29      3      5
12  14.11     30      3      5
13  14.12     29      3      5]

使用注释中的示例输出,并且仅考虑组前的 6:

[    state
6       5
7       5
8       5
9       5
10      5
11      5
12      5
13      5
14      5
15      5
16      5
17      5
18      5
19      5,
     state
50      5
51      5
52      5
53      5
54      5
55      5
56      5
57      5]

如果你想要所有的数字:


m1 = df['state'].eq(5)
m2 = df['state'].eq(6)
m3 = m1.where(m1|m2).ffill()
dfs = [g for k,g in df[m3&~m2].groupby(m2.cumsum())]

输出:

[    state
6       5
7       5
8       5
9       5
10      5
11      5
12      5
13      5
14      5
15      5
16      5
17      5
18      5
19      5
20      4
21      3
22      5
23      5
24      5
25      5
26      5
27      5
28      5
29      1
30      2
31      5
32      5
33      5,
     state
50      5
51      5
52      5
53      5
54      5
55      5
56      5
57      5
58      4
59      1
60      2
61      3
62      4
63      4]

评论

0赞 RomanPerekhrest 8/23/2023
带有行索引的记录不应该存在(它不在周期内)5
0赞 mozway 8/23/2023
@RomanPerekhrest不清楚,OP 只是说有两个周期,但我会用另一种方法更新
0赞 Karma_X 8/23/2023
@mozway 感谢您的回复。正如 Roman 所说,行索引 5 不应该在那里
0赞 RomanPerekhrest 8/23/2023
@mozway,OP说,关于他的评论:这是关于6666665555555555555543555555512555666666666666666655555555412344666666666
0赞 mozway 8/23/2023
@Karma_X好的,那就使用第二种方法
2赞 Andrej Kesely 8/23/2023 #2

IIUC,您可以尝试:

df = pd.DataFrame(
    {
        "state": list(
            "6666665555555555555543555555512555666666666666666655555555412344666666666"
        )
    }
)
df["state"] = df["state"].astype(int)


# remove the initial values 'till 6
df = df.loc[df["state"].eq(6).idxmax() :]

mask = df["state"].eq(6)
for _, g in df.groupby((mask != mask.shift()).cumsum()):
    if (eq5 := g["state"].eq(5)).any():
        g = g.loc[eq5.idxmax() :]
        print(g)
        print("-" * 80)

指纹:

    state
6       5
7       5
8       5
9       5
10      5
11      5
12      5
13      5
14      5
15      5
16      5
17      5
18      5
19      5
20      4
21      3
22      5
23      5
24      5
25      5
26      5
27      5
28      5
29      1
30      2
31      5
32      5
33      5
--------------------------------------------------------------------------------
    state
50      5
51      5
52      5
53      5
54      5
55      5
56      5
57      5
58      4
59      1
60      2
61      3
62      4
63      4
--------------------------------------------------------------------------------

评论

1赞 Karma_X 8/23/2023
嘿@Andrej Kesely,非常感谢你的回答。这对我来说非常有效。