有没有更有效的方法来重新格式化 pandas 数据框?

Is there a more efficient way to reformat a pandas dataframe?

我正在研究 CPU 数据的异常检测模型,我当前的数据帧结构如下(10k+ 服务器和 168 小时):

Server Hour1 Hour2 Hour3
server1 val1.1 val1.2 val1.3
server2 val2.1 val 2.2 val2.3

我需要它的结构如下:

Server time Value
server1 0 value0
server1 1 value1
server2 0 value0
server2 1 value1

问题是有 10k 多台服务器,每台服务器有 168 个小时值,因此迭代需要很长时间。有没有更有效的方法来进行这种转换?

我目前的尝试是创建一个带有嵌套 for 循环的新 df,如下所示:

for index, row in df.iterrows():
    for n in range(0,167):
        new_df.loc[len(new_df.index)] = row
        new_df.iat[len(new_df.index)-1, 2] = n

for index, row in new_df.iterrows():
    for i, r in df.iterrows():
        new_df_ts = row[2]
        if(row[0] == r[0]):
            new_df.iat[index, 3] = df.iat[i, 2 + new_df_ts]


使用wide_to_long

import pandas as pd
import io
df = pd.read_csv(io.StringIO("""
Server  Hour1   Hour2   Hour3
server1 val1.1  val1.2  val1.3
server2 val2.1  val2.2  val2.3"""), sep="\t")
df = pd.wide_to_long(df, "Hour", "Server", "Time") \
    .rename(columns={"Hour": "Value"}) \
    .reset_index()

这导致

    Server  Time    Value
0  server1     1   val1.1
1  server2     1   val2.1
2  server1     2   val1.2
3  server2     2   val2.2
4  server1     3   val1.3
5  server2     3   val2.3

或者,使用 melt,然后从 Time 列中删除 Hour 文本。

df = df.melt("Server", var_name="Time")
df["Time"] = df["Time"].str.strip("Hour").astype(int)

然后对 TimeValue 列执行任何需要的额外处理,例如从时间段中减去 1。如果需要,使用 df.replace or df["Value"].str.replace 更改值。