循环遍历 pandas 数据框列中的列表元素以在新列中返回列表

Posted

技术标签:

【中文标题】循环遍历 pandas 数据框列中的列表元素以在新列中返回列表【英文标题】:Loop through elements of list in a pandas dataframe column to return a list in new column 【发布时间】:2020-05-03 16:36:07 【问题描述】:

我有一个包含列表的列的数据框,我正在尝试遍历数据框中的每一行并与该行的列表中的每个元素连接。我正在尝试编写代码以实现“分子物种”中显示的结果。对此的任何想法将不胜感激。

数据框 =

import pandas as pd
df = pd.DataFrame('molecule': ['a',
                                'b',
                                'c',
                                'd',
                                'e'],
                   'species' : [['dog'],
                                ['horse','pig'],
                                ['cat', 'dog'],
                                ['cat','horse','pig'],
                                ['chicken','pig']])

我试图通过迭代行和列表元素来创建新列,将“分子”与“物种”中包含的列表中的每个元素连接起来。

df['molecule_species'] = [['a dog'],
                          ['b horse','b pig'],
                          ['c cat', 'c dog'],
                          ['d cat','d horse','d pig'],
                          ['e chicken','e pig']]

【问题讨论】:

this 问题有帮助吗?你也可以考虑参考concat方法。 所有解决方案都能满足您的需求,但正如您所见,它们在某些时候都需要对行进行循环。 pandas 并不意味着存储复杂的对象,如列表,通常处理 pandas 中对象的最高效方法是远离 pandas(Andy L. 的解决方案)。似乎您需要的所有信息都可以在 df.explode('species') 获得,并且该格式更适合以后使用 pandas 进行操作。 【参考方案1】:

您可以尝试双重列表理解。在处理 pandas 单元格内的子列表和字符串连接时,列表理解比使用内置的 pandas 方法快得多。

df['molecule_species'] = [[mol+' '+ a_spec for a_spec in specs] 
                                      for mol, specs in zip(df.molecule, df.species)]

Out[87]:
  molecule            species         molecule_species
0        a              [dog]                  [a dog]
1        b       [horse, pig]         [b horse, b pig]
2        c         [cat, dog]           [c cat, c dog]
3        d  [cat, horse, pig]  [d cat, d horse, d pig]
4        e     [chicken, pig]       [e chicken, e pig]

【讨论】:

建议:from itertools import product, chain; df['molecule_species'] = [list(chain.from_iterable(product([first], last))) for first, last in zip(df.molecule, df.species)]?【参考方案2】:

熊猫 > 0.25.0

使用Series.explode,然后使用join, 用GroupBy.agg返回列表:

df['molecule_species'] = (df.explode('species')
                            .apply(' '.join,axis=1)
                            .groupby(level=0)
                            .agg(list) )
print(df)

  molecule            species         molecule_species
0        a              [dog]                  [a dog]
1        b       [horse, pig]         [b horse, b pig]
2        c         [cat, dog]           [c cat, c dog]
3        d  [cat, horse, pig]  [d cat, d horse, d pig]
4        e     [chicken, pig]       [e chicken, e pig]

熊猫

df['molecule_species']=(df.reindex(df.index.repeat(df.species.str.len()))
                          .assign(species=np.concatenate(df.species.values))
                          .apply(' '.join,axis=1)
                          .groupby(level=0)
                          .agg(list) )
print(df)
  molecule            species         molecule_species
0        a              [dog]                  [a dog]
1        b       [horse, pig]         [b horse, b pig]
2        c         [cat, dog]           [c cat, c dog]
3        d  [cat, horse, pig]  [d cat, d horse, d pig]
4        e     [chicken, pig]       [e chicken, e pig]

另一种方法是Series.str.cat

df2 = df.explode('species')
df['molecule_species']=df2['molecule'].str.cat(df2['species'],sep=' ').groupby(level=0).agg(list)

【讨论】:

一点注意,pandas 的版本必须大于0.25.0explode【参考方案3】:

你可以试试这个,

>>> import pandas as pd
>>> df = pd.DataFrame('molecule': ['a',
                                'b',
                                'c',
                                'd',
                                'e'],
                   'species' : [['dog'],
                                ['horse','pig'],
                                ['cat', 'dog'],
                                ['cat','horse','pig'],
                                ['chicken','pig']])

>>> df['molecule_species'] = (df
    .apply(lambda x: [x['molecule'] + ' ' + m for m in x['species']], axis=1))
>>> df
  molecule            species         molecule_species
0        a              [dog]                  [a dog]
1        b       [horse, pig]         [b horse, b pig]
2        c         [cat, dog]           [c cat, c dog]
3        d  [cat, horse, pig]  [d cat, d horse, d pig]
4        e     [chicken, pig]       [e chicken, e pig]

【讨论】:

老实说,这应该有更多的赞成票。是的,apply 很慢,但是使用列表的 DataFrame 是无法解决的。此解决方案比爆炸更快,而且还简洁 +1。 @ALollz:比起apply,我更喜欢列表理解。但是,我同意它比explode 更快。赞成:) +1

以上是关于循环遍历 pandas 数据框列中的列表元素以在新列中返回列表的主要内容,如果未能解决你的问题,请参考以下文章

在新的 pandas 数据框列中计算日期时间差(以年、月等为单位)

将列表列表中的值映射到 Pandas 数据框列

使用 pandas 重命名数据框列中的元素

以字符串形式存储在 Pandas 数据框列中的解析列表

检查列表中的单词并在 pandas 数据框列中删除这些单词

根据每个句子的第一个单词将 pandas 数据框列中的字符串列表分解为新列