我有一个主数据框和几个小数据框(DF_0, DF_1,…),每个都有一个正常运行时间列。
DF_main:
(some columns) uptime
0 . 90094
1 . 90154
2 . 90214
3 . 90274
4 . 90334
. . .
. . .
. . .
1178 . 160774
1179 . 160834
1180 . 160894
. . .
. . .
. . .
1200 . 34
1201 . 94
1202 . 154
1203 . 214
DF_0:
(some columns) uptime
2 . 90094
25 . 90154
45 . 90214
23213 . 160834
23235 . 160894
23258 . 160954
25321 . 154
25359 . 214
把这些数据帧看作系统日志。
- 正常运行时间 显示系统启动后经过的时间。
- DF_main 表示每60秒发生的主要事件。
- df_0, df_1,…表示与主事件一起发生的事件。但并不是每次都发生。
DF_main的uptime可以从任意数字开始,下一行的值总是加+60,除非有时系统可以重置,下一个uptime值变成"(任何uptime值)mod 60";(正如您在DF_main中的第1200行中看到的那样)。当它重置时,它会为每个数据帧重置。
我需要从uptime列中的所有值中减去第一个正常运行时间。但由于正常运行时间值的重置,减去的值变为负值。
基本上我想:
- 将DF_main的第一个正常运行时间更改为0,并将下一个值增加60。
- 否定所有重置,改变正常运行时间值,就像每个数据帧没有重置一样。
如果没有系统/正常运行时间重置,这很容易做到。但是重置让我很困惑。
我知道第一个事件的对应时间戳,所以如果我能做到这一点,我就知道哪个事件发生在哪个日期和时间,通过时间戳和正常运行时间。
我想要得到的是这样的:
DF_main:
(some columns) uptime
0 . 0
1 . 60
2 . 120
3 . 180
4 . 240
. . .
. . .
. . .
1178 . 70680
1179 . 70740
1180 . 70800
. . .
. . .
. . .
1200 . 72000
1201 . 72060
1202 . 72120
DF_0:
(some columns) uptime
. 0
. 60
. 120
. 70740
. 70800
. 70860
. 72060
. 72120
我尝试了下面代码的一些变化,至少可以用DF_0实现它,但不能。
first_uptime = int(float(DF_main.iloc[0]['uptime']))
DF_0['uptime'] = DF_0['uptime'].apply(lambda x: x - first_uptime).where(lambda x: x>0, 0)
更新:我使用了for循环,因为我不想在数据框中迭代。如果你能想到一个没有for循环的解决方案,请告诉我。
for index, row in DT_0.iterrows():
if (row.uptime - first_uptime < 0):
first_uptime = row.uptime
DF_0.at[index, 'uptime'] = row.uptime - first_uptime
first_uptime = int(float(DF_main.iloc[0]['uptime']))
for index, row in DF_main.iterrows():
if (row.uptime - first_uptime < 0):
first_uptime = row.uptime
DF_main.at[index, 'uptime'] = row.uptime - first_uptime
假设正常运行时间的减少是重置的明确指示,这里有一个计算累计正常运行时间的通用方法(忽略重置,即使日志值是不规则的)。
import pandas as pd
def add_calc_uptime(df, t0=0):
# Determine when a reset occurred:
resets = df['uptime'].diff() < 0
# Make a new variable to denote each run between resets
df['run_id'] = resets.cumsum()
# Group results by run
uptime_by_run_id = df[['run_id', 'uptime']].groupby('run_id')
cum_uptimes_by_run = {}
for i, x in uptime_by_run_id:
# Calculate the uptime values for each run
cum_uptimes = x['uptime'].diff().cumsum()
# Replace NaN value in first row
cum_uptimes.iloc[0] = 0
# Add final time from previous run to current run
cum_uptimes = cum_uptimes + t0
cum_uptimes_by_run[i] = cum_uptimes
t0 = cum_uptimes.iloc[-1]
# Add results to dataframe
df['Uptime Calc'] = pd.concat(cum_uptimes_by_run.values())
return df
data = [90094, 90154, 90214, 90274, 90334, 34, 94, 154]
DF_main = pd.DataFrame(data, columns=['uptime'])
print(add_calc_uptime(DF_main))
data = [90094, 90154, 90214, 160834, 160894, 160954, 154, 214]
index = [2, 25, 45, 23213, 23235, 23258, 25321, 25359]
DF_0 = pd.DataFrame(data, index=index, columns=['uptime'])
print(add_calc_uptime(DF_0))
输出:
uptime run_id Uptime Calc
0 90094 0 0.0
1 90154 0 60.0
2 90214 0 120.0
3 90274 0 180.0
4 90334 0 240.0
5 34 1 240.0
6 94 1 300.0
7 154 1 360.0
uptime run_id Uptime Calc
2 90094 0 0.0
25 90154 0 60.0
45 90214 0 120.0
23213 160834 0 70740.0
23235 160894 0 70800.0
23258 160954 0 70860.0
25321 154 1 70860.0
25359 214 1 70920.0
注意:这还假设重置的持续时间为零,或者如果不是,则在重置开始前的最后一个报告之后进程没有继续运行。