【问题标题】:Convert yearly wide table to weekly long table将年宽表转换为周长表
【发布时间】:2021-09-01 18:35:44
【问题描述】:

我正在处理 pandas DataFrame 中的气候数据,该数据帧目前采用宽表格式,其中每一行代表特定地区的一年数据,而每周变量在列中。

有没有一种方法可以转换表格,以便有一个额外的“周”列,并且每周的变量值都列在列中?


例如,我的表目前看起来是这样的,其中变量后缀表示周数:

ID Year precip1 precip2 precip3 max_temp1 max_temp2 max_temp3
1100 2000 5.3 3.0 3.1 13.3 15.3 3.1
1100 2001 6.6 3.2 1.1 11.3 12.3 6.1
5903 2000 3.4 0.5 2.1 10.3 18.3 8.1
5903 2001 1.7 3.8 8.1 12.3 16.3 5.1

但我希望结果表如下所示:

ID Year Week precip max_temp
1100 2000 1 5.3 13.3
1100 2000 2 3.0 15.3
1100 2000 3 3.1 3.1
1100 2001 1 6.6 11.3
1100 2001 2 3.2 12.3
1100 2001 3 1.1 6.1
5903 2000 1 3.4 10.3
5903 2000 2 0.5 18.3
5903 2000 3 2.1 8.1
5903 2001 1 1.7 12.3
5903 2001 2 3.8 16.3
5903 2001 3 8.1 5.1

我尝试在整个 DataFrame 上使用 pd.melt(),但结果表不是我想要的。

【问题讨论】:

  • 试试wide_to_longpd.wide_to_long(df,i=['ID', 'Year'], stubnames=['precip', 'max_temp'], j='Week', suffix=".").reset_index()
  • @sammywemmy 添加的内容绝对有效!更清洁的选项。
  • 刚刚测试过这个。这100%是我想要的。谢谢!

标签: python python-3.x pandas dataframe


【解决方案1】:

让我们将您的初始 DataFrame 命名为 dfso。以下代码将使用melt 完成您想要的操作:

# Unpivot precipitation columns
dfp = dfso[["ID", "Year", "precip1", "precip2", "precip3"]].melt(["ID", "Year"], var_name="Week", value_name="precip")
# Clean the Week column
dfp["Week"] = dfp["Week"].str.replace("precip", "")

# Unpivot max temperature columns
dft = dfso[["ID", "Year", "max_temp1", "max_temp2", "max_temp3"]].melt(["ID", "Year"], var_name="Week", value_name="max_temp")
# Clean the Week column
dft["Week"] = dft["Week"].str.replace("max_temp", "")

# Merge both for desired result
result = dfp.merge(dft, on=["ID", "Year", "Week"], how="inner")

更新:

使用dft["Week"] = dft["Week"].str.replace("max_temp", "") 而不是更快的dft["Week"].apply(lambda x: x.replace("max_temp", ""))(这是max_temp 的情况,但适用于两种转换)。感谢@tdy 回复中的评论。

另一个选项(感谢对问题的评论)可能是:

result = pd.wide_to_long(
    dfso,
    i=["ID", "Year"],
    stubnames=["precip", "max_temp"],
    j="Week",
    suffix="."
).reset_index()

【讨论】:

  • 请注意,如果行数超过 ~100 行,Series.replaceSeries.apply 快得多,即 dfp.Week.replace('precip', ''); dft.Week.replace('max_temp', '')
  • 你是对的。我遇到的一个细微差别是您需要在替换之前添加str。我更新了我的解决方案。谢谢。
猜你喜欢
  • 1970-01-01
  • 2022-01-24
  • 2021-09-22
  • 1970-01-01
  • 2017-11-04
  • 1970-01-01
  • 2014-08-16
  • 2018-03-29
  • 1970-01-01
相关资源
最近更新 更多