在pandas中扁平化Series,即元素为列表的Series

16 投票
4 回答
17860 浏览
提问于 2025-04-18 08:30

我有一个这样的序列:

s = Series([['a','a','b'],['b','b','c','d'],[],['a','b','e']])

看起来像这样:

0       [a, a, b]
1    [b, b, c, d]
2              []
3       [a, b, e]
dtype: object

我想统计一下我总共有多少个元素。 我尝试的一些简单方法,比如:

s.values.hist()

或者

s.values.flatten()

都没有成功。 我哪里做错了呢?

4 个回答

-1

我个人非常喜欢在数据框中使用数组,每个项目对应一列。这样做能让你拥有更多的功能。所以,我有一个替代的方法。

>>> raw = [['a', 'a', 'b'], ['b', 'b', 'c', 'd'], [], ['a', 'b', 'e']]
>>> df = pd.DataFrame(raw)
>>> df
Out[217]: 
      0     1     2     3
0     a     a     b  None
1     b     b     c     d
2  None  None  None  None
3     a     b     e  None

现在,看看每一行有多少个值。

>>> df.count(axis=1)
Out[226]: 
0    3
1    4
2    0
3    3

在这里使用 sum() 函数就能得到你想要的结果。

其次,关于你在评论中提到的:获取分布。这里可能有更简洁的方法,但我还是更喜欢下面这个,而不是评论中给你的提示。

>>> foo = [col.value_counts() for x, col in df.iteritems()]
>>> foo
Out[246]: 
[a    2
 b    1
 dtype: int64, b    2
 a    1
 dtype: int64, b    1
 c    1
 e    1
 dtype: int64, d    1
 dtype: int64]

foo 现在包含了每一列的分布。列的解释还是“第x个值”,也就是说第0列包含了你数组中所有“第一个值”的分布。

接下来的步骤是“把它们加起来”。

>>> df2 = pd.DataFrame(foo)
>>> df2
Out[266]: 
    a   b   c   d   e
0   2   1 NaN NaN NaN
1   1   2 NaN NaN NaN
2 NaN   1   1 NaN   1
3 NaN NaN NaN   1 NaN
>>> test.sum(axis=0)
Out[264]: 
a    3
b    4
c    1
d    1
e    1
dtype: float64

需要注意的是,对于这些非常简单的问题,列表系列和每个项目都有列的数据框之间的区别不大,但一旦你想进行真正的数据处理,后者能提供更多的功能。此外,它可能更高效,因为你可以使用pandas的内部方法。

0
import itertools
word_lists=[['apple','orange'],['red','yellow']]
vocab=list(set(itertools.chain.from_iterable(raw_data.word_lists)))

在这里输入图片描述

16

如果我们继续使用原问题中的 pandas Series,从 Pandas 0.25.0 版本开始,有一个很不错的选项就是 Series.explode() 方法。这个方法可以把列表“炸开”,变成多行数据,每一行的索引会重复。

原来的 Series 如下:

s = pd.Series([['a','a','b'],['b','b','c','d'],[],['a','b','e']])

我们来用这个方法“炸开”它,得到的 Series 中,索引会重复。这个索引表示的是原始列表中的位置。

>>> s.explode()
Out:
0      a
0      a
0      b
1      b
1      b
1      c
1      d
2    NaN
3      a
3      b
3      e
dtype: object

>>> type(s.explode())
Out:
pandas.core.series.Series

现在我们可以用 Series.value_counts() 来统计元素的数量:

>>> s.explode().value_counts()
Out:
b    4
a    3
d    1
c    1
e    1
dtype: int64

如果想要统计 NaN 值(缺失值),可以这样做:

>>> s.explode().value_counts(dropna=False)
Out:
b      4
a      3
d      1
c      1
e      1
NaN    1
dtype: int64

最后,使用 Series.plot() 来绘制直方图:

>>> s.explode().value_counts(dropna=False).plot(kind = 'bar')

Series 的直方图

2
s.map(len).sum()

这个方法很好用。s.map(len) 会对每个元素使用 len() 函数,计算出每个元素的长度,然后返回一个包含所有长度的列表。接着,你只需要对这个列表使用 sum 函数,就能得到所有长度的总和。

撰写回答