Pandas (III)

Antes de nada, el contexto, para esta serie de entradas se va a usar lo siguiente:

Versión de Python:      3.3.1 (default, Apr 10 2013, 19:05:32) 
[GCC 4.6.3]
Versión de Pandas:      0.13.1
Versión de Numpy:       1.8.1
Versión de Matplotlib:  1.3.1

 

Y sin más preámbulos seguimos con esta tercera parte de la serie.

Trabajando con datos, indexación, selección,...

¿Cómo podemos seleccionar, añadir, eliminar, mover,..., columnas, filas,...?

Para seleccionar una columna solo hemos de usar el nombre de la columna y pasarlo como si fuera un diccionario (o un atributo).

Para añadir una columna simplemente hemos de usar un nombre de columna no existente y pasarle los valores para esa columna.

Para eliminar una columna podemos usar del o el método pop del DataFrame.

Para mover una columna podemos usar una combinación de las metodologías anteriores.

Por ejemplo, vemos a seleccionar los valores de una columna:

df = pd.DataFrame(np.random.randn(5,3),
                       index = ['primero','segundo','tercero','cuarto','quinto'],
                       columns = ['velocidad', 'temperatura','presion'])
print(df['velocidad'])
print(df.velocidad)

Hemos creado un DataFrame y para acceder a la columna velocidad lo podemos hacer de dos formas. O bien usando el nombre de la columna como si fuera una clave de un diccionario o bien usando el nombre de la columna como si fuera un atributo. En el caso de que los nombres de las columnas sean números, la segunda opción no podríais usarla...

Vamos a añadir una columna nueva al DataFrame. Es algo tan sencillo como usar un nombre de columna no existente y pasarle los datos:

df['velocidad_maxima'] = np.random.randn(df.shape[0])
print(df)

Y el resultado sería:

         velocidad  temperatura   presion  velocidad_maxima
primero   0.175374     0.384571 -0.575126         -0.474630
segundo  -0.133466     0.987833  0.305844         -0.746577
tercero  -0.418224     0.603431  0.128822          1.545612
cuarto   -0.320517    -0.643183  0.319838          0.634203
quinto    0.955521    -0.295541 -1.277743          2.389485

[5 rows x 4 columns]

 

Pero qué pasa si quiero añadir la columna en un lugar específico. Para ello podemos usar el método insert (y de paso vemos como podemos borrar una columna):

# forma 1 (borramos la columna 'velocidad_maxima' que está al final del df usando del)
#         (Colocamos la columna eliminada en la posición que especifiquemos)
print(df)
columna = df['velocidad_maxima']
del df['velocidad_maxima']
print(df)
print(columna)
df.insert(1, 'velocidad_maxima', columna)
print(df)

El resultado del DataFrame paso a paso sería:

         velocidad  temperatura   presion  velocidad_maxima
primero   0.175374     0.384571 -0.575126         -0.474630
segundo  -0.133466     0.987833  0.305844         -0.746577
tercero  -0.418224     0.603431  0.128822          1.545612
cuarto   -0.320517    -0.643183  0.319838          0.634203
quinto    0.955521    -0.295541 -1.277743          2.389485

[5 rows x 4 columns]
         velocidad  temperatura   presion
primero   0.175374     0.384571 -0.575126
segundo  -0.133466     0.987833  0.305844
tercero  -0.418224     0.603431  0.128822
cuarto   -0.320517    -0.643183  0.319838
quinto    0.955521    -0.295541 -1.277743

[5 rows x 3 columns]
primero   -0.474630
segundo   -0.746577
tercero    1.545612
cuarto     0.634203
quinto     2.389485
Name: velocidad_maxima, dtype: float64
         velocidad  velocidad_maxima  temperatura   presion
primero   0.175374         -0.474630     0.384571 -0.575126
segundo  -0.133466         -0.746577     0.987833  0.305844
tercero  -0.418224          1.545612     0.603431  0.128822
cuarto   -0.320517          0.634203    -0.643183  0.319838
quinto    0.955521          2.389485    -0.295541 -1.277743

[5 rows x 4 columns]

 

Una forma alternativa sería usando el método pop:

# forma 2 (borramos usando el método pop y añadimos la columna borrada en la última posición de nuevo)
print(df)
columna = df.pop('velocidad_maxima')
print(df)
print(columna)
df.insert(3, 'velocidad_maxima', columna)
print(df)

Cuyo resultado, paso a paso sería:

         velocidad  velocidad_maxima  temperatura   presion
primero   0.175374         -0.474630     0.384571 -0.575126
segundo  -0.133466         -0.746577     0.987833  0.305844
tercero  -0.418224          1.545612     0.603431  0.128822
cuarto   -0.320517          0.634203    -0.643183  0.319838
quinto    0.955521          2.389485    -0.295541 -1.277743

[5 rows x 4 columns]
         velocidad  temperatura   presion
primero   0.175374     0.384571 -0.575126
segundo  -0.133466     0.987833  0.305844
tercero  -0.418224     0.603431  0.128822
cuarto   -0.320517    -0.643183  0.319838
quinto    0.955521    -0.295541 -1.277743

[5 rows x 3 columns]
primero   -0.474630
segundo   -0.746577
tercero    1.545612
cuarto     0.634203
quinto     2.389485
Name: velocidad_maxima, dtype: float64
         velocidad  temperatura   presion  velocidad_maxima
primero   0.175374     0.384571 -0.575126         -0.474630
segundo  -0.133466     0.987833  0.305844         -0.746577
tercero  -0.418224     0.603431  0.128822          1.545612
cuarto   -0.320517    -0.643183  0.319838          0.634203
quinto    0.955521    -0.295541 -1.277743          2.389485

[5 rows x 4 columns]

 

Para seleccionar datos concretos de un DataFrame podemos usar el índice, una rebanada, valores booleanos, la columna,...

print('Seleccionamos la columna de velocidades')
print(df['velocidad'])
Seleccionamos la columna de velocidades
primero    0.175374
segundo   -0.133466
tercero   -0.418224
cuarto    -0.320517
quinto     0.955521
Name: velocidad, dtype: float64
print('Seleccionamos todas las columnas cuyo índice es igual a tercero')
print(df.xs('tercero'))
Seleccionamos todas las columnas cuyo índice es igual a tercero
velocidad        -0.418224
temperatura       0.603431
presion           0.128822
velocidad_maxima  1.545612
Name: tercero, dtype: float64
print('Seleccionamos todas las columnas cuyo índice está entre tercero y quinto')
print('Daos cuenta que en este caso los índices son inclusivos')
print(df.ix['tercero':'quinto'])
Seleccionamos todas las columnas cuyo índice está entre tercero y quinto
Daos cuenta que en este caso los índices son inclusivos
         velocidad  temperatura   presion  velocidad_maxima
tercero  -0.418224     0.603431  0.128822          1.545612
cuarto   -0.320517    -0.643183  0.319838          0.634203
quinto    0.955521    -0.295541 -1.277743          2.389485

[3 rows x 4 columns]
print('Seleccionamos todos los valores de velocidad donde la temperatura > 0')
print(df[df['temperatura' > 0]['velocidad'])
Seleccionamos todos los valores de velocidad donde la temperatura > 0
primero    0.175374
segundo   -0.133466
tercero   -0.418224
Name: velocidad, dtype: float64
print('Seleccionamos todos los valores de una columna por índice usando una')
print('rebanada (slice) de enteros')
print('Daos cuenta que en este caso el límite superior de la rebanada no se')
print('incluye (Python tradicional)')
print(df.ix[1:3])
Seleccionamos todos los valores de una columna por índice usando una
rebanada (slice) de enteros
Daos cuenta que en este caso el límite superior de la rebanada no se
incluye (Python tradicional)
         velocidad  temperatura   presion  velocidad_maxima
segundo  -0.133466     0.987833  0.305844         -0.746577
tercero  -0.418224     0.603431  0.128822          1.545612

[2 rows x 4 columns]
print(u'Seleccionamos filas y columnas')
print(df.ix[1:3, ['velocidad', 'presion']])
Seleccionamos filas y columnas
         velocidad   presion
segundo  -0.133466  0.305844
tercero  -0.418224  0.128822

[2 rows x 2 columns]
# Algunas de las cosas anteriores se pueden realizar sin usar los métodos .ix() o .xs()</span>
print(df['velocidad]
segundo   -0.133466
tercero   -0.418224
Name: velocidad, dtype: float64
# Da igual si colocamos el slice primero y después las columnas:
df['velocidad'][1:3] == df[1:3]['velocidad']
segundo    True
tercero    True
Name: velocidad, dtype: bool

 

En lo anterior he estado usando los métodos .ix(), .xs() para obtener partes del DataFrame. Son herramientas muy flexibles que nos permiten acceder a los datos de forma muy personalizada. Otras opciones sería usar los métodos .loc(), .iloc(), .select(). Es importante tener en cuenta que las series devueltas cuando se indexa un DataFrame son solo vistas y no una copia de los propios datos. Por tanto, debes ser precavido cuando manipulas los datos (al igual que sucede con los numpy arrays y otros tipos de datos). Lo siguiente (hecho con numpy arrays) es equivalente para las estructuras de datos de Pandas.

# Vista, ¡Cuidado!
a = np.random.rand(5)
data = a[0:2]
data[:] = -999
print(a)
# Copias
a = np.random.rand(5)
data = a[0:2].copy()
data[:] = -999
print(a)
a = np.random.rand(5)
data = 1 * a[0:2]
data[:] = -999
print(a)
a = np.random.rand(5)
np.copyto(data, a[0:2]) # En este caso, data tiene que existir
data[:] = -999
print(a)
a = np.random.rand(5)
data = np.array(a[0:2])
data[:] = -999
print(a)
[ -9.99000000e+02  -9.99000000e+02   7.18723608e-01   5.30962716e-01
   3.43706883e-01]
[ 0.20812195  0.36386055  0.17570252  0.31071035  0.38838464]
[ 0.37175682  0.36962863  0.14481144  0.80786818  0.82803089]
[ 0.89958739  0.00190588  0.14769624  0.3378831   0.74536315]
[ 0.19285654  0.51489647  0.19612007  0.52342758  0.2006809 ]

 

Para acceder a los valores de los índices podemos usar .index.

df.index
Index(['primero', 'segundo', 'tercero', 'cuarto', 'quinto'], dtype='object')

 

Para acceder a los valores de las columnas podemos usar .columns.

df.columns
Index(['velocidad', 'temperatura', 'presion', 'velocidad_maxima'], dtype='object')

 

Otra vez hemos llegado al final. ¡¡Estad atentos a la próxima entrega!!

Kiko Correoso

Licenciado y PhD en Ciencias Físicas, especializado en temas de física, meteorología, climatología, energías renovables, estadística, aprendizaje automático, análisis y visualización de datos. Apasionado de Python y su comunidad. Fundador de pybonacci y editor del sitio en el que se divulga Python, Ciencia y el conocimiento libre en español.

More Posts

Follow Me:
TwitterLinkedIn

8 thoughts on “Pandas (III)

  1. Muchisimas Gracias por tus tutoriales, son muy didácticos.
    Te quería hacer una consulta: Necesito hacer una busqueda en una columna de un dataFrame pero es una búsqueda tipo excel, es decir, necesito que la búsqueda arroje todas las filas cuyos datos de la columna ‘a’ contengan ‘elec’ siendo los datos de la columna a, por ejemplo: electricidad, agua, electrico…

    1. Hay varias formas de hacer eso en Pandas. Un ejemplo sería:

      df[df['a'].apply(lambda st: 'elec' in st)]

      donde df es tu dataframe.

      1. Genial!!!. Muchas gracias por tu solución, estoy empezando y no conocía la función apply que junto con lambda me parece muy potente.

        Te agradezco enormemente tus tutoriales, para mi son imprescindibles.

      2. Pandas no lo he encontrado ni simple ni evidente. Hace muchas cosas complejas y entenderlo bien no es sencillo de primeras.

      3. Buenas tardes! Muchísimas felicidades por tus tutoriales! Tengo una duda parecida a la que tuvo Paola (en mi caso busco la palabra exacta) pero al ejecutar tu solución me devuelve “TypeError: argument of type ‘float’ is not iterable”. ¿Se te ocurre cual puede ser el problema?

        Muchas gracias!

      4. Sin más datos es difícil saber lo que está pasando. Parece que tu columna no es una columna, sino un solo valor ‘float’ y no se puede iterar sobre el mismo y, por tanto, usar ‘apply’´…

  2. Hola!
    Me gustaría saber como puedo en python transformar n columnas que indican n ciudades donde se indica numero de veces que cada usuario ha visitado, en 1 columna que sea ciudad y numero de veces.
    Mil gracias por la ayuda

Leave a Reply

Your email address will not be published. Required fields are marked *