我要实现的目标是转换类似于但大于开始的数据帧,并以 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
答案 0 :(得分:3)
首先在所有没有列的列中创建MultiIndex
,并用DataFrame.set_index
进行空格分隔,然后在列中用Series.str.split
创建MultiIndex
(空格是默认值,因此分隔符不是必需指定),按DataFrame.stack
进行整形,按DataFrame.sort_index
和DataFrame.reset_index
的最后一层MultiIndex
按的第二级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()