2016-10-17 3 views
5

Я хочу заменить отрицательные значения на nan только для определенных столбцов. Самый простой способ может быть:Pandas: Как условно назначить несколько столбцов?

for col in ['a', 'b', 'c']: 
    df.loc[df[col ] < 0, col] = np.nan 

df может иметь много столбцов, и я только хочу, чтобы сделать это в конкретные столбцы.

Есть ли способ сделать это в одной строке? Похоже, это должно быть легко, но я не смог понять.

ответ

11

Я не думаю, что вы получите намного проще, чем это:

>>> df = pd.DataFrame({'a': np.arange(-5, 2), 'b': np.arange(-5, 2), 'c': np.arange(-5, 2), 'd': np.arange(-5, 2), 'e': np.arange(-5, 2)}) 
>>> df 
    a b c d e 
0 -5 -5 -5 -5 -5 
1 -4 -4 -4 -4 -4 
2 -3 -3 -3 -3 -3 
3 -2 -2 -2 -2 -2 
4 -1 -1 -1 -1 -1 
5 0 0 0 0 0 
6 1 1 1 1 1 
>>> df[df[cols] < 0] = np.nan 
>>> df 
    a b c d e 
0 NaN NaN NaN -5 -5 
1 NaN NaN NaN -4 -4 
2 NaN NaN NaN -3 -3 
3 NaN NaN NaN -2 -2 
4 NaN NaN NaN -1 -1 
5 0.0 0.0 0.0 0 0 
6 1.0 1.0 1.0 1 1 
6

использование loc и where

cols = ['a', 'b', 'c'] 
df.loc[:, cols] = df[cols].where(df[cols].where.ge(0), np.nan) 

демонстрация

df = pd.DataFrame(np.random.randn(10, 5), columns=list('abcde')) 
df 

enter image description here

cols = list('abc') 
df.loc[:, cols] = df[cols].where(df[cols].ge(0), np.nan) 
df 

enter image description here


Вы можете ускорить его с Numpy

df[cols] = np.where(df[cols] < 0, np.nan, df[cols]) 

сделать то же самое.


времени

def gen_df(n): 
    return pd.DataFrame(np.random.randn(n, 5), columns=list('abcde')) 

, поскольку задания является важной частью этого, я создать df с нуля каждый цикл. Я также добавил время для создания df.

для n = 10000

enter image description here

для n = 100000

enter image description here

+0

@jezrael nice catch – piRSquared

5

Вот способ:

df[df.columns.isin(['a', 'b', 'c']) & (df < 0)] = np.nan 
4

Вы можете использовать np.where для достижения этой цели:

In [47]: 
df = pd.DataFrame(np.random.randn(5,5), columns=list('abcde')) 
df 

Out[47]: 
      a   b   c   d   e 
0 0.616829 -0.933365 -0.735308 0.665297 -1.333547 
1 0.069158 2.266290 -0.068686 -0.787980 -0.082090 
2 1.203311 1.661110 -1.227530 -1.625526 0.045932 
3 -0.247134 -1.134400 0.355436 0.787232 -0.474243 
4 0.131774 0.349103 -0.632660 -1.549563 1.196455 

In [48]:  
df[['a','b','c']] = np.where(df[['a','b','c']] < 0, np.NaN, df[['a','b','c']]) 
df 

Out[48]: 
      a   b   c   d   e 
0 0.616829  NaN  NaN 0.665297 -1.333547 
1 0.069158 2.266290  NaN -0.787980 -0.082090 
2 1.203311 1.661110  NaN -1.625526 0.045932 
3  NaN  NaN 0.355436 0.787232 -0.474243 
4 0.131774 0.349103  NaN -1.549563 1.196455 
1

Если он должен быть один вкладыш:

df[['a', 'b', 'c']] = df[['a', 'b', 'c']].apply(lambda c: [x>0 and x or np.nan for x in c]) 
3

Sure , просто выберите нужные столбцы из маски:

(df < 0)[['a', 'b', 'c']] 

Вы можете использовать эта маска в df[(df < 0)[['a', 'b', 'c']]] = np.nan.

Смежные вопросы