将2列中的值合并为pandas数据帧中的单个列

问题描述 投票:28回答:4

我正在寻找一种行为类似于在T-SQL中合并的方法。我有两列(A列和B列)在pandas数据帧中稀疏填充。我想使用以下规则创建一个新列:

  1. 如果A列中的值不为null,请将该值用于新列C
  2. 如果A列中的值为null,请使用B列中的值作为新列C

就像我提到的,这可以通过coalesce函数在MS SQL Server中完成。我还没有找到一个好的pythonic方法;一个存在吗?

python pandas numpy dataframe
4个回答
65
投票

使用combine_first()

In [16]: df = pd.DataFrame(np.random.randint(0, 10, size=(10, 2)), columns=list('ab'))

In [17]: df.loc[::2, 'a'] = np.nan

In [18]: df
Out[18]:
     a  b
0  NaN  0
1  5.0  5
2  NaN  8
3  2.0  8
4  NaN  3
5  9.0  4
6  NaN  7
7  2.0  0
8  NaN  6
9  2.0  5

In [19]: df['c'] = df.a.combine_first(df.b)

In [20]: df
Out[20]:
     a  b    c
0  NaN  0  0.0
1  5.0  5  5.0
2  NaN  8  8.0
3  2.0  8  2.0
4  NaN  3  3.0
5  9.0  4  9.0
6  NaN  7  7.0
7  2.0  0  2.0
8  NaN  6  6.0
9  2.0  5  2.0

12
投票

试试这个..更容易记住:

df['c'] = np.where(df["a"].isnull(), df["b"], df["a"] )

这稍快一点:qazxsw poi

df['c'] = np.where(df["a"].isnull() == True, df["b"], df["a"] )

9
投票

%timeit df['d'] = df.a.combine_first(df.b) 1000 loops, best of 3: 472 µs per loop %timeit df['c'] = np.where(df["a"].isnull(), df["b"], df["a"] ) 1000 loops, best of 3: 291 µs per loop 是最直接的选择。我在下面概述了其他几个。我将概述一些解决方案,一些适用于不同的情况。

Case #1: Non-mutually Exclusive NaNs

并非所有行都具有NaN,并且这些combine_firsts在列之间不是互斥的。

NaN

让我们先在df = pd.DataFrame({ 'a': [1.0, 2.0, 3.0, np.nan, 5.0, 7.0, np.nan], 'b': [5.0, 3.0, np.nan, 4.0, np.nan, 6.0, 7.0]}) df a b 0 1.0 5.0 1 2.0 3.0 2 3.0 NaN 3 NaN 4.0 4 5.0 NaN 5 7.0 6.0 6 NaN 7.0 上结合起来。

a

Series.mask
df['a'].mask(pd.isnull, df['b'])
# df['a'].mask(df['a'].isnull(), df['b'])

0 1.0 1 2.0 2 3.0 3 4.0 4 5.0 5 7.0 6 7.0 Name: a, dtype: float64

Series.where

您可以使用df['a'].where(pd.notnull, df['b']) 0 1.0 1 2.0 2 3.0 3 4.0 4 5.0 5 7.0 6 7.0 Name: a, dtype: float64 使用类似的语法。

或者,首先在np.where上组合,切换周围的条件。


Case #2: Mutually Exclusive Positioned NaNs

所有行都有bs,它们在列之间是互斥的。

NaN

df = pd.DataFrame({ 'a': [1.0, 2.0, 3.0, np.nan, 5.0, np.nan, np.nan], 'b': [np.nan, np.nan, np.nan, 4.0, np.nan, 6.0, 7.0]}) df a b 0 1.0 NaN 1 2.0 NaN 2 3.0 NaN 3 NaN 4.0 4 5.0 NaN 5 NaN 6.0 6 NaN 7.0

此方法就地工作,修改原始DataFrame。这是此用例的有效选项。

Series.update

df['b'].update(df['a']) # Or, to update "a" in-place, # df['a'].update(df['b']) df a b 0 1.0 1.0 1 2.0 2.0 2 3.0 3.0 3 NaN 4.0 4 5.0 5.0 5 NaN 6.0 6 NaN 7.0

Series.add

df['a'].add(df['b'], fill_value=0) 0 1.0 1 2.0 2 3.0 3 4.0 4 5.0 5 6.0 6 7.0 dtype: float64 + DataFrame.fillna

DataFrame.sum

0
投票

我遇到了这个问题,但想要合并多个列,从多个列中选择第一个非空值。我发现以下内容很有帮助:

构建虚拟数据

df.fillna(0).sum(1)

0    1.0
1    2.0
2    3.0
3    4.0
4    5.0
5    6.0
6    7.0
dtype: float64
import pandas as pd
df = pd.DataFrame({'a1': [None, 2, 3, None],
                   'a2': [2, None, 4, None],
                   'a3': [4, 5, None, None],
                   'a4': [None, None, None, None],
                   'b1': [9, 9, 9, 999]})

df

将a1 a2,a3合并到一个新列A中

    a1   a2   a3    a4   b1
0  NaN  2.0  4.0  None    9
1  2.0  NaN  5.0  None    9
2  3.0  4.0  NaN  None    9
3  NaN  NaN  NaN  None  999
def get_first_non_null(dfrow, columns_to_search):
    for c in columns_to_search:
        if pd.notnull(dfrow[c]):
            return dfrow[c]
    return None

# sample usage:
cols_to_search = ['a1', 'a2', 'a3']
df['A'] = df.apply(lambda x: get_first_non_null(x, cols_to_search), axis=1)

print(df)
© www.soinside.com 2019 - 2024. All rights reserved.