进行以下从宽到长格式的数据帧转换的好方法?

时间:2019-03-31 14:31:46

标签: python python-3.x pandas dataframe

我要实现的目标是转换类似于但大于开始的数据帧,并以 Goal 结尾。我相信以下代码和输出可以更好地说明这一点,但列名的第一部分(日期除外)应成为列,而新列的第二部分值应称为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

2 个答案:

答案 0 :(得分:3)

首先在所有没有列的列中创建MultiIndex,并用DataFrame.set_index进行空格分隔,然后在列中用Series.str.split创建MultiIndex(空格是默认值,因此分隔符不是必需指定),按DataFrame.stack进行整形,按DataFrame.sort_indexDataFrame.reset_index的最后一层MultiIndexNested Json Data 的第二级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 :(得分:1)

另一个可能的选择是pd.wide_to_long()

df1 = pd.wide_to_long(df, ['type1', 'type2'], i = 'date', j ='source', sep =' ', suffix = '\w+').reset_index()