#python #python-3.x #pandas #dataframe
#python #python-3.x #pandas #фрейм данных
Вопрос:
Чего я пытаюсь достичь, так это преобразовать фрейм данных, аналогичный, но больше, чем здесь начинается, и в конечном итоге получить цель. Я полагаю, что следующие коды и выходные данные объясняют это лучше, чем я могу, но первые части имен столбцов (кроме даты) должны стать столбцами, а вторые части значениями нового столбца с именем source. У меня более двух типов и двух источников.
Фиктивные данные:
import pandas as pd
import numpy as np
import datetime as dt
n = 10
date = [dt.datetime.strftime(dt.datetime.now() dt.timedelta(days=x), '%Y-%m-%d') for x in range(n)]
rn1 = np.random.randint(0, 50, n)
rn2 = np.random.randint(-50, 1, n)
Начать:
data = {'date': date, 'type1 source1': rn1, 'type2 source1': rn1*100, 'type1 source2': rn2, 'type2 source2': rn2*100}
df = pd.DataFrame(data)
Вывод:
date type1 source1 type2 source1 type1 source2 type2 source2
0 2019-03-31 43 4300 -37 -3700
1 2019-04-01 42 4200 -34 -3400
2 2019-04-02 11 1100 -29 -2900
3 2019-04-03 38 3800 -31 -3100
4 2019-04-04 42 4200 -28 -2800
5 2019-04-05 31 3100 -50 -5000
6 2019-04-06 30 3000 -17 -1700
7 2019-04-07 19 1900 -18 -1800
8 2019-04-08 2 200 -43 -4300
9 2019-04-09 26 2600 -39 -3900
Цель:
data = {'date': date*2,'type1': np.concatenate([rn1, rn2]) , 'type2': np.concatenate([rn1*100, rn2*100]), 'source': np.concatenate([np.repeat('source1', n), np.repeat('source2', n)])}
df = pd.DataFrame(data)
Вывод:
date type1 type2 source
0 2019-03-31 43 4300 source1
1 2019-04-01 42 4200 source1
2 2019-04-02 11 1100 source1
3 2019-04-03 38 3800 source1
4 2019-04-04 42 4200 source1
5 2019-04-05 31 3100 source1
6 2019-04-06 30 3000 source1
7 2019-04-07 19 1900 source1
8 2019-04-08 2 200 source1
9 2019-04-09 26 2600 source1
10 2019-03-31 -37 -3700 source2
11 2019-04-01 -34 -3400 source2
12 2019-04-02 -29 -2900 source2
13 2019-04-03 -31 -3100 source2
14 2019-04-04 -28 -2800 source2
15 2019-04-05 -50 -5000 source2
16 2019-04-06 -17 -1700 source2
17 2019-04-07 -18 -1800 source2
18 2019-04-08 -43 -4300 source2
19 2019-04-09 -39 -3900 source2
Ответ №1:
Сначала создайте MultiIndex
из всех столбцов без столбцов с разделителем пробелов по DataFrame.set_index
, затем создайте MultiIndex
в столбцах по Series.str.split
(пробел — значение по умолчанию, поэтому разделитель указывать не обязательно), измените форму по DataFrame.stack
, отсортировав по второму уровню MultiIndex
по DataFrame.sort_index
с DataFrame.reset_index
и последнему rename
столбцу:
df = df.set_index('date')
df.columns = df.columns.str.split(expand=True)
df = (df.stack()
.sort_index(level=1)
.reset_index()
.rename(columns={'level_1':'source'}))
print (df)
date source type1 type2
0 2019-03-31 source1 43 4300
1 2019-04-01 source1 42 4200
2 2019-04-02 source1 11 1100
3 2019-04-03 source1 38 3800
4 2019-04-04 source1 42 4200
5 2019-04-05 source1 31 3100
6 2019-04-06 source1 30 3000
7 2019-04-07 source1 19 1900
8 2019-04-08 source1 2 200
9 2019-04-09 source1 26 2600
10 2019-03-31 source2 -37 -3700
11 2019-04-01 source2 -34 -3400
12 2019-04-02 source2 -29 -2900
13 2019-04-03 source2 -31 -3100
14 2019-04-04 source2 -28 -2800
15 2019-04-05 source2 -50 -5000
16 2019-04-06 source2 -17 -1700
17 2019-04-07 source2 -18 -1800
18 2019-04-08 source2 -43 -4300
19 2019-04-09 source2 -39 -3900
Комментарии:
1. не могли бы вы, пожалуйста, объяснить, как
sort_index(level=1)
работает спасибо2. @Akhilesh — Конечно, при сортировке
MultiIndex
— Индекс создается по 2 столбцам по второму «столбцу» — второму уровню мультииндекса.
Ответ №2:
Также другой возможной альтернативой является pd.wide_to_long():
df1 = pd.wide_to_long(df, ['type1', 'type2'], i = 'date', j ='source', sep =' ', suffix = 'w ').reset_index()