Хороший способ сделать следующее широкое в длинное преобразование формата кадра данных? - PullRequest
2 голосов
/ 31 марта 2019

То, чего я пытаюсь добиться, - это преобразовать фрейм данных, похожий на Start здесь, и получить Goal .Я полагаю, что следующие коды и выходные данные объясняют это лучше, чем я, но первые части имен столбцов (кроме даты) должны стать столбцами, а значения вторых частей нового столбца, называемого источником.У меня более двух типов и два источника.

Фиктивные данные:

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

Ответы [ 2 ]

3 голосов
/ 31 марта 2019

Сначала создайте 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 голос
/ 31 марта 2019

Также возможна другая альтернатива: pd.wide_to_long () :

df1 = pd.wide_to_long(df, ['type1', 'type2'], i = 'date', j ='source', sep =' ', suffix = '\w+').reset_index()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...