tutorial tablas recorrer para notebook libreria leer hacer funciones filtrar filas español datos data como agregar python pandas

python - tablas - Aplicar la función a cada fila de marco de datos de pandas para crear dos nuevas columnas



pandas python tutorial español pdf (4)

Tengo un panda DataFrame, st contiene varias columnas:

<class ''pandas.core.frame.DataFrame''> DatetimeIndex: 53732 entries, 1993-01-07 12:23:58 to 2012-12-02 20:06:23 Data columns: Date(dd-mm-yy)_Time(hh-mm-ss) 53732 non-null values Julian_Day 53732 non-null values AOT_1020 53716 non-null values AOT_870 53732 non-null values AOT_675 53188 non-null values AOT_500 51687 non-null values AOT_440 53727 non-null values AOT_380 51864 non-null values AOT_340 52852 non-null values Water(cm) 51687 non-null values %TripletVar_1020 53710 non-null values %TripletVar_870 53726 non-null values %TripletVar_675 53182 non-null values %TripletVar_500 51683 non-null values %TripletVar_440 53721 non-null values %TripletVar_380 51860 non-null values %TripletVar_340 52846 non-null values 440-870Angstrom 53732 non-null values 380-500Angstrom 52253 non-null values 440-675Angstrom 53732 non-null values 500-870Angstrom 53732 non-null values 340-440Angstrom 53277 non-null values Last_Processing_Date(dd/mm/yyyy) 53732 non-null values Solar_Zenith_Angle 53732 non-null values dtypes: datetime64[ns](1), float64(22), object(1)

Quiero crear dos columnas nuevas para este marco de datos basadas en aplicar una función a cada fila del marco de datos. No quiero tener que llamar a la función varias veces (por ejemplo, haciendo dos llamadas de apply separado) ya que es bastante intensivo en términos de computación. He intentado hacer esto de dos maneras, y ninguna de ellas funciona:

Usando apply :

He escrito una función que toma una Series y devuelve una tupla de los valores que quiero:

def calculate(s): a = s[''path''] + 2*s[''row''] # Simple calc for example b = s[''path''] * 0.153 return (a, b)

Intentar aplicar esto al DataFrame da un error:

st.apply(calculate, axis=1) --------------------------------------------------------------------------- AssertionError Traceback (most recent call last) <ipython-input-248-acb7a44054a7> in <module>() ----> 1 st.apply(calculate, axis=1) C:/Python27/lib/site-packages/pandas/core/frame.pyc in apply(self, func, axis, broadcast, raw, args, **kwds) 4191 return self._apply_raw(f, axis) 4192 else: -> 4193 return self._apply_standard(f, axis) 4194 else: 4195 return self._apply_broadcast(f, axis) C:/Python27/lib/site-packages/pandas/core/frame.pyc in _apply_standard(self, func, axis, ignore_failures) 4274 index = None 4275 -> 4276 result = self._constructor(data=results, index=index) 4277 result.rename(columns=dict(zip(range(len(res_index)), res_index)), 4278 inplace=True) C:/Python27/lib/site-packages/pandas/core/frame.pyc in __init__(self, data, index, columns, dtype, copy) 390 mgr = self._init_mgr(data, index, columns, dtype=dtype, copy=copy) 391 elif isinstance(data, dict): --> 392 mgr = self._init_dict(data, index, columns, dtype=dtype) 393 elif isinstance(data, ma.MaskedArray): 394 mask = ma.getmaskarray(data) C:/Python27/lib/site-packages/pandas/core/frame.pyc in _init_dict(self, data, index, columns, dtype) 521 522 return _arrays_to_mgr(arrays, data_names, index, columns, --> 523 dtype=dtype) 524 525 def _init_ndarray(self, values, index, columns, dtype=None, C:/Python27/lib/site-packages/pandas/core/frame.pyc in _arrays_to_mgr(arrays, arr_names, index, columns, dtype) 5411 5412 # consolidate for now -> 5413 mgr = BlockManager(blocks, axes) 5414 return mgr.consolidate() 5415 C:/Python27/lib/site-packages/pandas/core/internals.pyc in __init__(self, blocks, axes, do_integrity_check) 802 803 if do_integrity_check: --> 804 self._verify_integrity() 805 806 self._consolidate_check() C:/Python27/lib/site-packages/pandas/core/internals.pyc in _verify_integrity(self) 892 "items") 893 if block.values.shape[1:] != mgr_shape[1:]: --> 894 raise AssertionError(''Block shape incompatible with manager'') 895 tot_items = sum(len(x.items) for x in self.blocks) 896 if len(self.items) != tot_items: AssertionError: Block shape incompatible with manager

Luego iba a asignar los valores devueltos desde apply a dos nuevas columnas utilizando el método que se muestra en esta pregunta . Sin embargo, ¡ni siquiera puedo llegar a este punto! Todo esto funciona bien si solo devuelvo un valor.

Usando un bucle:

Primero creé dos nuevas columnas del marco de datos y las establecí en None :

st[''a''] = None st[''b''] = None

Luego hice un bucle sobre todos los índices e intenté modificar estos valores None que tenía allí, pero las modificaciones que hice no parecían funcionar. Es decir, no se generó ningún error, pero el DataFrame no pareció modificarse.

for i in st.index: # do calc here st.ix[i][''a''] = a st.ix[i][''b''] = b

Pensé que ambos métodos funcionarían, pero ninguno de ellos lo hizo. Entonces, ¿qué estoy haciendo mal aquí? ¿Y cuál es la mejor manera, la más "pitónica" y "pandaónica" de hacer esto?



Otra solución más basada en Asignar nuevas columnas en cadenas de métodos :

st.assign(a = st[''path''] + 2*st[''row''], b = st[''path''] * 0.153)

Tenga en cuenta que assign siempre devuelve una copia de los datos, dejando intacto el DataFrame original.


Para hacer que el primer enfoque funcione, intente devolver una serie en lugar de una tupla (aplicar arroja una excepción porque no sabe cómo pegar las filas nuevamente ya que el número de columnas no coincide con el fotograma original).

def calculate(s): a = s[''path''] + 2*s[''row''] # Simple calc for example b = s[''path''] * 0.153 return pd.Series(dict(col1=a, col2=b))

El segundo enfoque debería funcionar si reemplazas:

st.ix[i][''a''] = a

con:

st.ix[i, ''a''] = a


Siempre uso lambdas y la función map() incorporada para crear nuevas filas combinando otras filas:

st[''a''] = map(lambda path, row: path + 2 * row, st[''path''], st[''row''])

Puede ser un poco más complicado de lo necesario para hacer combinaciones lineales de columnas numéricas. Por otro lado, creo que es bueno adoptarlo como una convención, ya que se puede usar con combinaciones más complicadas de filas (por ejemplo, trabajar con cadenas) o completar datos faltantes en una columna usando funciones de las otras columnas.

Por ejemplo, digamos que tiene una tabla con columnas de género y título, y faltan algunos de los títulos. Puede llenarlos con una función de la siguiente manera:

title_dict = {''male'': ''mr.'', ''female'': ''ms.''} table[''title''] = map(lambda title, gender: title if title != None else title_dict[gender], table[''title''], table[''gender''])