Python 合并包含列表对象的列

Python 合并包含列表对象的列,python,pandas,numpy,Python,Pandas,Numpy,我的问题类似于“”和“”,但由于我要合并的单元格包含列表,所有给定的答案都不起作用 简化后,我的df如下所示: players players1 players2 players3 1 ['1','2'] 2 ['2','4'] 3 ['1','4'] 4 ['1','5'] 5

我的问题类似于“”和“”,但由于我要合并的单元格包含列表,所有给定的答案都不起作用

简化后,我的df如下所示:

        players    players1    players2    players3
1       ['1','2']  
2       ['2','4']
3                  ['1','4']
4                              ['1','5']
5                                          ['3','5']
6
7                  ['3','4']
(因此我知道其中两列中永远不会有值。)

现在,我想添加一个新的列,其中包含以下列表:

        players    players1    players2    players3     players_combine
1       ['1','2']                                       ['1','2']
2       ['2','4']                                       ['2','4']
3                  ['1','4']                            ['1','4']
4                              ['1','5']                ['1','5']
5                                          ['3','5']    ['3','5']
6
7                  ['3','4']                            ['3','4']
我尝试了很多东西——主要是链接答案的变体,我的最后一个想法是级联np。但它不起作用。只有来自“玩家”的值显示在组合列中

df['players_combine'] = np.where(df.players.notnull(),df.players.values,np.where(df.players1.notnull(),df.players1.values,np.where(df.players2.notnull(),df.players2.values,np.where(df.players3.notnull(),df.players3.values,np.nan))))
编辑: 如评论中所述:df.head(5).to_dict()


如果任何空单元格是空字符串(
'
),请首先将其设置为NaN:

df[df==''] = np.nan
然后,选择每行中所有非NAN的最大值:

df.apply(lambda x: x[x.notnull()].max(), axis=1)
#1    [1, 2]
#2    [2, 4]
#3    [1, 4]
#4    [1, 5]
#5    [3, 5]
#6       NaN
#7    [3, 4]
df.loc[df.notnull().any(axis=1)]\
  .apply(lambda x: x[x.first_valid_index()], axis=1)
#1    [1, 2]
#2    [2, 4]
#3    [1, 4]
#4    [1, 5]
#5    [3, 5]
#7    [3, 4]
另一个有趣的解决方案(更快)是消除所有NaN行,然后在每行中找到第一个有效值:

df.apply(lambda x: x[x.notnull()].max(), axis=1)
#1    [1, 2]
#2    [2, 4]
#3    [1, 4]
#4    [1, 5]
#5    [3, 5]
#6       NaN
#7    [3, 4]
df.loc[df.notnull().any(axis=1)]\
  .apply(lambda x: x[x.first_valid_index()], axis=1)
#1    [1, 2]
#2    [2, 4]
#3    [1, 4]
#4    [1, 5]
#5    [3, 5]
#7    [3, 4]

因为您知道每行最多只能在一列中输入一个值,所以可以用
NaN
替换不关心的值,然后使用
.stack

在本例中,您似乎同时拥有
'nan'
'
字符串,这些字符串应首先替换为
np.nan

import numpy as np

df['players_combine'] = df.replace({'': np.NaN, 'nan': np.NaN}, regex=True).stack().reset_index(level=1, drop=True)
样本数据 输出:
分析你的
df.to_dict()
看起来,对于某些单元格,你有字符串
nan
,对于其他单元格,你有实际的
np.nan
,对于其他单元格,你甚至有空字符串
'

因此,首先通过统一空值来清理数据集:

df = df.replace({'nan':np.nan, '':np.nan})
然后您可以通过
轴=1

df['players_combine'] = df.agg(lambda s: s[~s.isnull()][0], axis=1)

由于一些格式错误的数据是我代码中的问题,而不是问题所在,所以我想添加一些关于所有不同选项性能的信息。我使用了np.where,因为它使用矢量化,而np.apply迭代行,因此存在巨大的性能差异


设置4*2000=8000行的测试df:

import pandas as pd
import numpy as np

l = [[['1','2'],np.NaN,np.NaN,np.NaN],
     [np.NaN,['2','3'],np.NaN,np.NaN],
    [np.NaN,np.NaN,['3','4'],np.NaN],
    [np.NaN,np.NaN,np.NaN,['4','5']]]

l=l*2000

df = pd.DataFrame(l)

df.columns = ['players','players1','players2','players3']

最佳选择:

%timeit df['players_combine'] = np.where(df.players.notnull(),df.players.values,np.where(df.players1.notnull(),df.players1.values,np.where(df.players2.notnull(),df.players2.values,np.where(df.players3.notnull(),df.players3.values,np.nan))))

100 loops, best of 3: 2.18 ms per loop
非常好的选择:

%timeit df.loc[df.notnull().any(axis=1)]\
  .apply(lambda x: x[x.first_valid_index()], axis=1)

100 loops, best of 3: 413 ms per loop
其他备选方案1:

%timeit df['players_combine'] = df.agg(lambda s: s[~s.isnull()][0], axis=1)

1 loop, best of 3: 4.71 s per loop
和2:

%timeit df['players_combine'] = df.apply(lambda x: x[x.notnull()].max(), axis=1)

1 loop, best of 3: 4.86 s per loop

您能将df.post
to_dict()
?单元格中不能有“无值”。它们里面到底有什么?空字符串、空列表、N?其他列中的空值是多少?它是一个空字符串,还是NaN,还是一个空列表?如果您发布
d=df.to_dict()
,我们只需执行
pd.DataFrame(d)
,并按原样复制数据帧:)@J_Scholz然后只需执行
df.head(5.to_dict()
)看来“南”一直是我的问题。我把它们当成真正的np.nan。现在是我的np.where行。谢谢,np.where解比这还要快。看看我的答案。
%timeit df['players_combine'] = df.apply(lambda x: x[x.notnull()].max(), axis=1)

1 loop, best of 3: 4.86 s per loop