2012-08-03 17 views
7

Tengo un Pandas DataFrame con cuatro columnas, A, B, C, D. Resulta que, a veces, los valores de B y C pueden ser 0. Por ello, deseo obtener lo siguiente:Pandas DataFrame Aplicar

B[i] = B[i] if B[i] else min(A[i], D[i]) 
C[i] = C[i] if C[i] else max(A[i], D[i]) 

donde he utilizado i para indicar una carrera en todas las filas de la trama. Con las pandas es fácil encontrar las filas que contienen cero columnas:

df[df.B == 0] and df[df.C == 0] 

sin embargo no tengo idea de cómo llevar a cabo fácilmente la transformación anterior. Puedo pensar en varios métodos ineficientes y poco eficientes (for bucles en todo el fotograma) pero nada simple.

Respuesta

8

Una combinación de indexación booleana y aplicación puede hacer el truco. Debajo de un ejemplo sobre la sustitución del elemento cero para la columna C.

In [22]: df 
Out[22]: 
    A B C D 
0 8 3 5 8 
1 9 4 0 4 
2 5 4 3 8 
3 4 8 5 1 

In [23]: bi = df.C==0 

In [24]: df.ix[bi, 'C'] = df[bi][['A', 'D']].apply(max, axis=1) 

In [25]: df 
Out[25]: 
    A B C D 
0 8 3 5 8 
1 9 4 9 4 
2 5 4 3 8 
3 4 8 5 1 
+1

Bastante limpio. Sin embargo, creo que puedes salirte con '.max (axis = 1)' en lugar de 'apply (...)'. –

+0

'max()' está bien también, por supuesto, creo que tengo un sesgo hacia 'aplicar' por la forma en que hizo la pregunta :-) –

2

Pruebe el método de la clase DataFrame 'iterrows' para iterar eficientemente a través de las filas de un DataFrame. Consulte el capítulo 6.7.2 de la guía pandas 0.8.1.

from pandas import * 
import numpy as np 

df = DataFrame({'A' : [5,6,3], 'B' : [0,0,0], 'C':[0,0,0], 'D' : [3,4,5]}) 

for idx, row in df.iterrows(): 
    if row['B'] == 0: 
     row['B'] = min(row['A'], row['D']) 
    if row['C'] == 0: 
     row['C'] = min(row['A'], row['D']) 
Cuestiones relacionadas