我有一个列表如下:
[['A'],
['America'],
['2017-39', '2017-40', '2017-41', '2017-42', '2017-43'],
[10.0, 6.0, 6.0, 6.0, 1.0],
[5.0,7.0,8.0,9.0,1.0],
,
['B'],
['Britan'],
['2017-38', '2017-39', '2017-40', '2017-41', '2017-42', '2017-43', '2017-44'],
[41.0, 27.0, 38.0, 36.0, 33.0, 41.0, 8.0],
[40.0, 38.0, 28.0, 27.0, 23.0, 65.0, 4.0]]
我想将其转换为应该看起来像
的数据框A America 2017-39 10.0 5.0
na na 2017-40 6.0 7.0
na na 2017-41 6.0 8.0
na na 2017-42 6.0 9.0
na na 2017-43 1.0 10.0
B Britan 2017-38 41.0 40.0
na na 2017-39 27.0 38.0
na na 2017-40 38.0 28.0
na na 2017-41 36.0 27.0
na na 2017-42 33.0 23.0
na na 2017-43 41.0 65.0
na na 2017-44 8.0 4.0
我如何编写代码使其成为可能,因为我对python很新,我很难。
我将非常感谢您在这方面帮助我的时间和精力
答案 0 :(得分:3)
import pandas as pd
data = [['A'],
['America'],
['2017-39', '2017-40', '2017-41', '2017-42', '2017-43'],
[10.0, 6.0, 6.0, 6.0, 1.0],
[5.0,7.0,8.0,9.0,1.0],
['B'],
['Britan'],
['2017-38', '2017-39', '2017-40', '2017-41', '2017-42', '2017-43', '2017-44'],
[41.0, 27.0, 38.0, 36.0, 33.0, 41.0, 8.0],
[40.0, 38.0, 28.0, 27.0, 23.0, 65.0, 4.0]]
result = {}
for letters, countries, dates, val1, val2 in zip(*[iter(data)]*5):
result[tuple(letters+countries)] = pd.DataFrame({'date':dates, 'val1':val1, 'val2':val2})
result = pd.concat(result)
print(result)
产量
date val1 val2
A America 0 2017-39 10.0 5.0
1 2017-40 6.0 7.0
2 2017-41 6.0 8.0
3 2017-42 6.0 9.0
4 2017-43 1.0 1.0
B Britan 0 2017-38 41.0 40.0
1 2017-39 27.0 38.0
2 2017-40 38.0 28.0
3 2017-41 36.0 27.0
4 2017-42 33.0 23.0
5 2017-43 41.0 65.0
6 2017-44 8.0 4.0
上面的主要想法是使用"grouper idiom" zip(*[iter(data)]*5)
将data
中的项目分组为5.这样,就可以使用
for letters, countries, dates, val1, val2 in zip(*[iter(data)]*5):
一次循环浏览5个data
项。
pd.concat
可以接受dict
个DataFrame作为输入,并将它们连接到一个DataFrame中,其中MultiIndex由dict
的键组成。
因此,for-loop
用于撰写数据框的dict
,
for letters, countries, dates, val1, val2 in zip(*[iter(data)]*5):
result[tuple(letters+countries)] = pd.DataFrame({'date':dates, 'val1':val1, 'val2':val2})
然后
result = pd.concat(result)
生成所需的DataFrame。
不是说你可以删除MultiIndex的最后一个级别:
In [91]: result.index = result.index.droplevel(level=-1)
In [92]: result
Out[92]:
date val1 val2
A America 2017-39 10.0 5.0
America 2017-40 6.0 7.0
America 2017-41 6.0 8.0
America 2017-42 6.0 9.0
America 2017-43 1.0 1.0
B Britan 2017-38 41.0 40.0
Britan 2017-39 27.0 38.0
Britan 2017-40 38.0 28.0
Britan 2017-41 36.0 27.0
Britan 2017-42 33.0 23.0
Britan 2017-43 41.0 65.0
Britan 2017-44 8.0 4.0
但我不建议这样做,因为它使索引非唯一:
In [96]: result.index.is_unique
Out[96]: False
这可能会导致未来的困难,因为一些Pandas操作只能处理具有唯一索引的DataFrame。
答案 1 :(得分:2)
一种解决方案是使用itertools
执行一些链接魔法。
我们使用了两个必要的习语:
zip
数据列表的长度以及标识符。chain.from_iterable
(分配给chainer
)合并每个第5个子列表。在这两种情况下,我们都会使用islice
来避免不必要地创建列表作为中间步骤。
data
定义为@ unutbu的帖子。
<强>解决方案强>
import pandas as pd
from itertools import chain, islice
chainer = chain.from_iterable
lens = list(map(len, islice(data, 2, None, 5)))
res = pd.DataFrame({'id1': list(chainer(list(j)+[np.nan]*(i-1) for i, j in
zip(lens, islice(data, 0, None, 5)))),
'id2': list(chainer(list(j)+[np.nan]*(i-1) for i, j in
zip(lens, islice(data, 1, None, 5)))),
'date': list(chainer(islice(data, 2, None, 5))),
'num1': list(chainer(islice(data, 3, None, 5))),
'num2': list(chainer(islice(data, 4, None, 5)))})
res = res[['id1', 'id2', 'date', 'num1', 'num2']]
<强>结果强>
print(res)
id1 id2 date num1 num2
0 A America 2017-39 10.0 5.0
1 NaN NaN 2017-40 6.0 7.0
2 NaN NaN 2017-41 6.0 8.0
3 NaN NaN 2017-42 6.0 9.0
4 NaN NaN 2017-43 1.0 1.0
5 B Britan 2017-38 41.0 40.0
6 NaN NaN 2017-39 27.0 38.0
7 NaN NaN 2017-40 38.0 28.0
8 NaN NaN 2017-41 36.0 27.0
9 NaN NaN 2017-42 33.0 23.0
10 NaN NaN 2017-43 41.0 65.0
11 NaN NaN 2017-44 8.0 4.0
答案 2 :(得分:2)
我正在使用groupby
并重新创建列
s=pd.DataFrame(lst).T
s.columns=s.columns//5
pd.concat([pd.DataFrame(x.values) for _,x in s.groupby(level=0,axis=1)]).dropna(axis=0,thresh=1)
Out[146]:
0 1 2 3 4
0 A America 2017-39 10 5
1 None None 2017-40 6 7
2 None None 2017-41 6 8
3 None None 2017-42 6 9
4 None None 2017-43 1 1
0 B Britan 2017-38 41 40
1 None None 2017-39 27 38
2 None None 2017-40 38 28
3 None None 2017-41 36 27
4 None None 2017-42 33 23
5 None None 2017-43 41 65
6 None None 2017-44 8 4