使用np.where有条件地将值分配给DF列

时间:2018-01-02 16:11:37

标签: python pandas dataframe

我尝试将某些列分组到单个列中的列表中。 如果其中一列包含NaN,则结果列应该只是NaN而不是列表。

df = pd.DataFrame({'a.0':[11, 1.1], 'a.5':[12, 1.2], 'a.10':[13, pd.np.NaN]})

DF的结果栏应如下:

    a.0   a.10   a.5   result
0 . 11.0  13.0   12.0  [11, 13, 12]
1 . 1.1   nan    1.2   nan

这两行完成了这项工作:

df['result'] = df[['a.0','a.10','a.5']].values.tolist()
df['result'] = pd.np.where(df[['a.0','a.10','a.5']].isnull().any(axis=1), pd.np.nan, df['result'])

我想知道如何在一条线上做到这一点。帮助将不胜感激

2 个答案:

答案 0 :(得分:2)

更新对于时间和大数据集cᴏʟᴅsᴘᴇᴇᴅ答案是最好的。列表理解总是在这里受到影响。我已经用时间更新了我以前的答案。

如果行中有任何np.nan,您可以使用itertuples并指定np.nan:

import pandas as pd
import numpy as np

df = pd.DataFrame({'a.0':np.random.choice(np.append(np.nan,np.arange(10)), 1000), 
                   'a.5':np.random.choice(10, 1000), 
                   'a.10':np.random.choice(10, 1000)})

# 3 solutions to solve the problem 
# Assign with df['results'] =
%timeit [np.nan if np.isnan(v).any() else list(v[1:]) for v in df.itertuples()]
%timeit pd.Series(df.values.tolist()).mask(df.isnull().any(1))
%timeit df.apply(lambda x : pd.Series([x.tolist()]) if ~x.isnull().any() else np.nan,1)

时序:

100 loops, best of 3: 8.38 ms per loop
1000 loops, best of 3: 772 µs per loop
1 loop, best of 3: 214 ms per loop

答案 1 :(得分:2)

df['result']=df.apply(lambda x : pd.Series([x.tolist()]) if ~x.isnull().any() else np.nan,1)
df
Out[30]: 
    a.0  a.10   a.5              result
0  11.0  13.0  12.0  [11.0, 13.0, 12.0]
1   1.1   NaN   1.2                 NaN
相关问题