将Pandas系列列表转换为数据框。

36

我有一个由列表组成的系列

import pandas as pd
s = pd.Series([[1, 2, 3], [4, 5, 6]])

我想要一个数据框,其中每一列都是一个列表。

使用 from_itemsfrom_recordsDataFrameSeries.to_frame 都似乎不起作用。

如何实现?

8个回答

27

正如@Hatshepsut在评论中指出的那样,from_items在0.23版本后已被弃用。该链接建议使用from_dict代替,因此旧答案可以修改为:

pd.DataFrame.from_dict(dict(zip(s.index, s.values)))

您可以这样使用from_items(假设您的列表长度相同):

pd.DataFrame.from_items(zip(s.index, s.values))

   0  1
0  1  4
1  2  5
2  3  6

或者

pd.DataFrame.from_items(zip(s.index, s.values)).T

   0  1  2
0  1  2  3
1  4  5  6

根据您所需的输出方式进行选择。

这比使用apply(如@Wen's answer中使用的方法,但也适用于不同长度的列表)要快得多:

%timeit pd.DataFrame.from_items(zip(s.index, s.values))
1000 loops, best of 3: 669 µs per loop

%timeit s.apply(lambda x:pd.Series(x)).T
1000 loops, best of 3: 1.37 ms per loop

并且

%timeit pd.DataFrame.from_items(zip(s.index, s.values)).T
1000 loops, best of 3: 919 µs per loop

%timeit s.apply(lambda x:pd.Series(x))
1000 loops, best of 3: 1.26 ms per loop

此外,@Hatshepsut的回答也非常快速(同样适用于不同长度的列表):

%timeit pd.DataFrame(item for item in s)
1000 loops, best of 3: 636 µs per loop

and

%timeit pd.DataFrame(item for item in s).T
1000 loops, best of 3: 884 µs per loop

最快的解决方案似乎是@Abdou的回答(经过Python 2的测试;也适用于长度不同的列表;在Python 3.6+中使用itertools.zip_longest):

%timeit pd.DataFrame.from_records(izip_longest(*s.values))
1000 loops, best of 3: 529 µs per loop

另外一个选项:

pd.DataFrame(dict(zip(s.index, s.values)))

   0  1
0  1  4
1  2  5
2  3  6

2
如果您想添加它,@Abdou的itertools解决方案似乎更快。但是需要使用额外的库。还可以注意到相同长度的限制是否适用? - Hatshepsut
1
@Hatshepsut:已添加。似乎不需要相同的长度,对于s = pd.Series([[1,2, 3,4], [4, 5,6]])也可以正常工作。 - Cleb
为什么要写s.apply(lambda x:pd.Series(x)),而不是直接写s.apply(pd.Series)呢? :) - Unknown artist
@KirillG:我从Wen的回答中获取了这个用于速度比较的内容。 - Cleb
3
from_items现在已被弃用。from_items是指从项目中创建DataFrame的方法。详细信息请参见链接:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.from_items.html - Hatshepsut
为了简单和易读起见,我建议将答案更改为:pd.DataFrame(s.to_dict()) - Arnon Erez

13

如果序列的长度非常长(超过1m),您可以使用:

s = pd.Series([[1, 2, 3], [4, 5, 6]])
pd.DataFrame(s.tolist())

12

尝试:

import numpy as np, pandas as pd
s = pd.Series([[1, 2, 3], [4, 5, 6]])
pd.DataFrame(np.vstack(s))

1
这个方法比Cleb的方法快得多。不错。 - AMA

8

按照以下方式遍历系列:

series = pd.Series([[1, 2, 3], [4, 5, 6]])
pd.DataFrame(item for item in series)

   0  1  2
0  1  2  3
1  4  5  6

非常快,应该将其添加到下面的计时中...(已赞) - Cleb

7

1
似乎是最快的解决方案(得到了赞同)。你可能想要补充说明这是一个Python3的解决方案;在Python 2中,它将是itertools.izip_longest - Cleb

3

您可能正在寻找

s.apply(lambda x:pd.Series(x))
   0  1  2
0  1  2  3
1  4  5  6

或者
 s.apply(lambda x:pd.Series(x)).T

Out[133]: 
   0  1
0  1  4
1  2  5
2  3  6

这里可能不是最好的选择,因为它似乎相当慢(请参见我的时间记录)。 - Cleb
@Cleb 尝试一下这个例子 s = pd.Series([[1,2, 3,4], [4, 5,6]]) 我考虑到列表长度不同的情况,如果它们长度相同,那么你的答案就更好了~ :) - BENY
1
当然,那么我的代码会失败,但是Hatshepsut的代码似乎仍然更快。我确实假设所有列表具有相同的长度,将添加此注释,感谢您指出这一点! - Cleb

2

注意:接受的答案中from_items()方法在最新版本的Pandas中已被废弃,应该使用from_dict()方法。如下所示:

from_dict()方法的用法如下:

pd.DataFrame.from_dict(dict(zip(s.index, s.values)))

## OR  

pd.DataFrame.from_dict(dict(zip(s.index, s.values))).T

请注意,使用from_dict()方法是目前最快速的方法:
%timeit pd.DataFrame.from_dict(dict(zip(s.index, s.values)))
376 µs ± 14.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

## OR

%timeit pd.DataFrame.from_dict(dict(zip(s.index, s.values))).T
487 µs ± 3.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

from_records 对这个答案有什么影响吗? - baxx

0
更好的方法是利用pandas在使用Series.values时输出一个numpy数组。 然后,您可以使用np.vstack将这个奇怪的集合转换为一堆记录,它会自动将所有数据解包成一个整洁的n_row x n_cols形状的numpy数组。
pd.DataFrame(np.vstack(my_serie.values), index=my_serie.index)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接