Pandas 系列列表到一个系列

Posted

技术标签:

【中文标题】Pandas 系列列表到一个系列【英文标题】:Pandas Series of lists to one series 【发布时间】:2015-09-02 07:12:13 【问题描述】:

我有一个 Pandas 系列的字符串列表:

0                           [slim, waist, man]
1                                [slim, waistline]
2                                     [santa]

如您所见,列表因长度而异。我想要一种有效的方法将其折叠成一个系列

0 slim
1 waist
2 man
3 slim
4 waistline
5 santa

我知道我可以使用

series_name.split(' ')

但我很难将这些字符串重新放入一个列表中。

谢谢!

【问题讨论】:

how to extract nested lists? 的可能重复项 对于那些希望做类似的事情但保持其他列保持机智的人,类似于枢轴,您可能需要查看this question and answer 【参考方案1】:

如果您的pandas 版本太旧而无法使用series_name.explode(),这也应该可以:

from itertools import chain

pd.Series(
    chain.from_iterable(
        value
        for i, value
        in series_name.iteritems()
    )
)

【讨论】:

【参考方案2】:

在pandas 版本0.25.0 中出现了series 和dataframes 的新方法'explode'。旧版本没有这种方法。

它有助于构建您需要的结果。

例如你有这样的系列:

import pandas as pd

s = pd.Series([
    ['slim', 'waist', 'man'],
    ['slim', 'waistline'],
    ['santa']])

然后就可以使用了

s.explode()

要得到这样的结果:

0         slim
0        waist
0          man
1         slim
1    waistline
2        santa

如果是数据框:

df = pd.DataFrame(
  's': pd.Series([
    ['slim', 'waist', 'man'],
    ['slim', 'waistline'],
    ['santa']
   ]),
   'a': 1
)

你会有这样的DataFrame:

                    s  a
0  [slim, waist, man]  1
1   [slim, waistline]  1
2             [santa]  1

s 列上应用爆炸:

df.explode('s')

会给你这样的结果:

           s  a
0       slim  1
0      waist  1
0        man  1
1       slim  1
1  waistline  1
2      santa  1

如果您的系列包含空列表

import pandas as pd

s = pd.Series([
    ['slim', 'waist', 'man'],
    ['slim', 'waistline'],
    ['santa'],
    []
])

然后运行 ​​explode 将为空列表引入 NaN 值,如下所示:

0         slim
0        waist
0          man
1         slim
1    waistline
2        santa
3          NaN

如果不想这样,可以dropna方法调用:

s.explode().dropna()

要得到这个结果:

0         slim
0        waist
0          man
1         slim
1    waistline
2        santa

Dataframes 也有dropna 方法:

df = pd.DataFrame(
  's': pd.Series([
    ['slim', 'waist', 'man'],
    ['slim', 'waistline'],
    ['santa'],
    []
   ]),
   'a': 1
)

在没有 dropna 的情况下运行 explode

df.explode('s')

将导致:

           s  a
0       slim  1
0      waist  1
0        man  1
1       slim  1
1  waistline  1
2      santa  1
3        NaN  1

使用dropna:

df.explode('s').dropna(subset=['s'])

结果:

           s  a
0       slim  1
0      waist  1
0        man  1
1       slim  1
1  waistline  1
2      santa  1

【讨论】:

【参考方案3】:

你也可以试试:

combined = []
for i in s.index:
    combined = combined + s.iloc[i]

print(combined)

s = pd.Series(combined)
print(s)

输出:

['slim', 'waist', 'man', 'slim', 'waistline', 'santa']

0         slim
1        waist
2          man
3         slim
4    waistline
5        santa

dtype: object

【讨论】:

【参考方案4】:

可以使用此函数进行展平和取消展平

def flatten(df, col):
    col_flat = pd.DataFrame([[i, x] for i, y in df[col].apply(list).iteritems() for x in y], columns=['I', col])
    col_flat = col_flat.set_index('I')
    df = df.drop(col, 1)
    df = df.merge(col_flat, left_index=True, right_index=True)

    return df

去扁平化:

def unflatten(flat_df, col):
    flat_df.groupby(level=0).agg(**c:'first' for c in flat_df.columns, col: list)

展开后,除了列顺序,我们得到相同的数据框:

(df.sort_index(axis=1) == unflatten(flatten(df)).sort_index(axis=1)).all().all()
>> True

【讨论】:

【参考方案5】:
series_name.sum()

完全满足您的需求。请确保它是一系列列表,否则您的值将被连接(如果是字符串)或添加(如果是 int)

【讨论】:

【参考方案6】:

这是一个只使用 pandas 函数的简单方法:

import pandas as pd

s = pd.Series([
    ['slim', 'waist', 'man'],
    ['slim', 'waistline'],
    ['santa']])

然后

s.apply(pd.Series).stack().reset_index(drop=True)

提供所需的输出。在某些情况下,您可能希望保存原始索引并添加第二级来索引嵌套元素,例如

0  0         slim
   1        waist
   2          man
1  0         slim
   1    waistline
2  0        santa

如果这是您想要的,只需从链中省略 .reset_index(drop=True)

【讨论】:

请记住,s.apply(pd.Series) 正在创建一个 DataFrame,其宽度是原始系列中最长的列表。因此,如果您有一个包含 10 个列表的系列,其中一个是 500 个条目,它将生成一个包含 10 行、500 列以及可能有很多 NA 的 DataFrame! 另外请记住,如果输入为空,apply 将返回一个系列,并且系列对象没有堆栈方法... 对我来说太慢了。【参考方案7】:

您可以尝试使用 itertools.chain 来简单地展平列表:

In [70]: from itertools import chain
In [71]: import pandas as pnd
In [72]: s = pnd.Series([['slim', 'waist', 'man'], ['slim', 'waistline'], ['santa']])
In [73]: s
Out[73]: 
0    [slim, waist, man]
1     [slim, waistline]
2               [santa]
dtype: object
In [74]: new_s = pnd.Series(list(chain(*s.values)))
In [75]: new_s
Out[75]: 
0         slim
1        waist
2          man
3         slim
4    waistline
5        santa
dtype: object

【讨论】:

【参考方案8】:

您基本上只是想在此处展平嵌套列表。

您应该能够迭代该系列的元素:

slist =[]
for x in series:
    slist.extend(x)

或者更流畅(但更难理解)的列表理解:

slist = [st for row in s for st in row]

【讨论】:

【参考方案9】:

您可以使用如下的列表连接运算符 -

lst1 = ['hello','world']
lst2 = ['bye','world']
newlst = lst1 + lst2
print(newlst)
>> ['hello','world','bye','world']

或者你可以使用list.extend()函数如下-

lst1 = ['hello','world']
lst2 = ['bye','world']
lst1.extend(lst2)
print(lst1)
>> ['hello', 'world', 'bye', 'world']

使用extend 函数的好处是它可以处理多种类型,而concatenation 运算符仅在LHS 和RHS 都是列表时才有效。

extend函数的其他例子-

lst1.extend(('Bye','Bye'))
>> ['hello', 'world', 'Bye', 'Bye']

【讨论】:

以上是关于Pandas 系列列表到一个系列的主要内容,如果未能解决你的问题,请参考以下文章

Pandas:使用系列进行列表查找

pandas 中的新列 - 通过应用列表 groupby 将系列添加到数据框

如何在 pandas 系列列表中使用 OneHotEncoder?

将元组列表转换为 Pandas 系列

在 pandas 中展平系列,即元素为列表的系列

如果 pandas 系列的值是一个列表,如何获取每个元素的子列表?