Как повернуть pandas df, где каждый заголовок столбца равен часу, а каждая строка — дате

#python #pandas

#python #pandas

Вопрос:

Итак, у меня есть pandas df, который выглядит следующим образом введите описание изображения здесь

где каждый столбец — это час дня, указанный в столбце даты. Я хотел бы повернуть этот df так, чтобы каждый час дня был отдельной строкой. Похоже на это

введите описание изображения здесь

где было бы 24 строки для каждого часа каждой даты.

Я попытался использовать pd.melt, используя следующее

 hourly_value = ['00:00','01:00','02:00','03:00','04:00','05:00','06:00','07:00','08:00','09:00','10:00','11:00','12:00']
df = df.melt(id_vars = ['DATE'], var_name = hourly_value, value_name = ('Hourly Precip'))
  

но продолжайте получать ошибку «Ошибка индекса: слишком много уровней: индекс имеет только 1 уровень, а не 2». Я также изучал использование df.pivot, но я начинаю думать, что мой df имеет формат, сильно отличающийся от большинства примеров.

Ответ №1:

Один из способов получить то, что вы хотите, — это:

  1. Используется .set_index('DATE') для превращения DATE столбца в индекс.

  2. Используйте .stack() , чтобы также включить столбцы в индекс, создавая MultiIndex , где строка для каждой даты вставляется в качестве второго уровня в индексе.

  3. Используется .reset_index() для преобразования всех уровней индекса обратно в строки.

Следующий фрагмент иллюстрирует:

 import numpy as np
import pandas as pd

dates = [f"1/{i}/2020" for i in range(1, 21)]
cols = ["DATE"]   [str(i)   ":00" for i in range(25)]
zeros = np.zeros((len(dates), len(cols) - 1))
data = list([[x]   list(y) for x, y in zip(dates, zeros)])

df = pd.DataFrame(data=data, columns=cols)

df2 = (
    df.set_index("DATE") # makes the DATE column the index
    .stack()             # stacks 
    .reset_index()
    .rename(columns={"level_1": "Time", 0: "Value"})
)
print(df2.head())
  

Какие результаты:

        DATE  Time  Value
0  1/1/2020  0:00    0.0
1  1/1/2020  1:00    0.0
2  1/1/2020  2:00    0.0
3  1/1/2020  3:00    0.0
4  1/1/2020  4:00    0.0
  

Комментарии:

1. Это именно то, что я пытался сделать. теперь, когда я вижу, что это возможно, как бы я это сделал, если бы у меня было 4 дополнительных столбца (я исключил их из исходного формата df), связанных с каждым часовым измерением? Я бы просто продолжил переименовывать с .rename(columns = {'level_1':'Time',0:'Value', 1 :'Value 2 name',2:'Value 3 name'} помощью и так далее?

2. .stack() помещает все исходные столбцы в один столбец (тот, который назван 0 ), поэтому я не думаю, что это сработает для вашего последующего сценария. Если вы хотите, чтобы несколько значений для каждого часа были отдельными столбцами в конечном результате, вы можете попробовать разделить столбцы исходного фрейма данных, применив описанную выше процедуру к каждому отдельно, а затем объединить их обратно.

3. да, именно так я начал заниматься последующим. спасибо, что подтвердили мои мысли по этому поводу

Ответ №2:

Попробуйте это :

  pd.melt( df.reset_index(), id_vars=['DATE'], var_name='hour', value_name='Hourly Precip')
  

Комментарии:

1. df.reset_index — это то, что я искал. Я пытался использовать reset index = True, но из-за этого продолжал получать ошибку. Я не знал, что смогу сделать это и таким образом. Это дало мне общий формат, который я искал, хотя он все еще нуждается в некоторых манипуляциях. Спасибо!