TransWikia.com

¿Como recorrer un dataframe como una lista de listas?

Stack Overflow en español Asked by Raimundovp on December 23, 2021

soy nuevo usando pandas y estoy tratando de hacer un modelo de optimizacion leyendo datos de un excel, pero no encuentro cómo recorrer los datos de una forma que no sea filas por columnas, por favor si me pudieran ayudar. Intentaré explicarlo con un ejemplo pequeño.

Tengo un modelo de optimización hecho con la librería mip de python donde tengo el parametro score en una tabla de la siguiente manera:

        name degree  score
      aparna    MBA     90
      aparna    BCA     40
      pankaj    MBA     80
      pankaj    BCA     98
      sudhir    MBA    101
      sudhir    BCA     73

Donde name y degree serían los sets.
Y tengo la tabla escrita como lista de listas para poder recorrerla, ya que así se presentan los parametros en la documentación de mip

datos=[[90, 40], [80, 98], [101, 73]]

entonces para hacer una sumatoria hago lo siguiente:

for n in N:
    print(xsum(datos[n][d] for d in D))

>>output: + 130.0
          + 178.0
          + 174.0

Esto indica "Para cada name la suma de los score segun el degree".
Ahora me gustaría hacer una expresión parecida para la sumatoria, pero con datos siendo un dataframe, donde pueda recorrer y sumar los scores segun name o degree ya que son muchas tablas en excel y no las quiero poner cada una en listas. Si me pudieran ayudar, ya que solo he encontrado formas para recorrer filas por columnas con iterrows(), itertuples(), etc, pero ninguno para hacerlo de una forma parecida a como es con listas. Gracias!

2 Answers

Si me pudieran ayudar, ya que solo he encontrado formas para recorrer filas por columnas con iterrows(), itertuples(), etc.

df.iterrows()

El método iterrows() te va devolver una lista con varias tuplas. Cada tupla tiene dos elementos, el indice de la fila y un objeto de Pandas , que es como un miniDataFrame cada fila. Si es un iterable se puede usar un ciclo for, si es un iterable con tuplas de dos elementos se pueden usar dos variables temporales.

tot = 0
for index,row in df.iterrows():  
    tot += float(row["score"])

En este ejemplo se usa index para representar el primer elemento de cada tupla, y row para el segundo. Si bien row es en esencia un DataFrame entonces se puede acceder por columna, como si se tratara de un diccionario.

Se hace el casteo a float() para tener la mayor precisión posible, ya que si se tratara de elementos decimales al castear con int() se eliminaría la parte decimal del número. De igual manera, es válido castear a entero.

Esto al ser una sola instrucción, es fácil de traducir a formato de lista y sumarlo con sum():

Sums start and the items of an iterable from left to right and returns the total.

tot = sum([row["score"] for index,row in df.iterrows()])

df.itertuples()

Se puede pensar que no es una manera válida, debido a que devuelve un objeto tipo map. Realmente da para mucho este método, ya que es válido castear estos objetos a listas.

list_ = map(lambda a: list(a),df.itertuples())
tot = 0
for value in list_:
    tot += value[3]

Aquí lo primero que se hace es generar una lista que solo contenga el tercer elemento de la lista de cada elemento de itertuples().

¿Por qué específicamente el tercer elemento?

Al castear en lista se obtiene algo como esto:

  [0,"valor_1","valor_2",...,]
   *     *         *      *
   |     |         |      |
indice   a         b     etc...

Donde a y b son valores de columnas posicionadas en el DataFrame. Los valores de la columna "score" se posicionarían en el cuarto lugar, el indice 3.

Al igual que con iterrows(), esto se puede simplificar muchísimo con una compresión:

list_ = [list(cols)[3] for cols in df.itertuples()]
tot = sum(list_)

También con map()

Return an iterator that applies function to every item of iterable.

list_ = sum(map(lambda a: a[3],df.itertuples()))

me gustaría hacer una expresión parecida para la sumatoria, pero con datos siendo un dataframe, donde pueda recorrer y sumar los scores segun name o degree ya que son muchas tablas en excel y no las quiero poner cada una en listas.

La manera más fácil

Es tan simple como acceder a una columna en específico y usar sum(). Puedes acceder a una columna en específica como si fuera un diccionario, es decir:

columna = df["columna"]

Esto te va a retornar una lista con todos los elementos de dicha columna, por lo tanto sería igual de válido

list_ = sum(df["score"])

Si por alguna razón solo sabes en que posición está la columna, pero no su nombre. Puedes hacer uso del atributo columns del DataFrame, este retorna una lista con los nombres de las columna. También sería válido

list_ = sum(df[df.columns[2]])

Con cualquier manera se obtendría 482 o bien 482.0

ninguno para hacerlo de una forma parecida a como es con listas.

Realmente, cuando se trata de Pandas es muy difícil no toparse con lista :)

Sumando solo fragmentos de listas

Si bien cualquier de las anteriores maneras son válidas para obtener la sumatoria total de una columna, se puede obtener una sumatoria no total. Esto debido a que eventualmente el número obtenido fue una lista.

Un ejemplo sumando de dos en dos

output = []
col = df["score"]

for i in range(0,len(col),2):
    output.append(col[i] + col[i + 1])

output es una lista vacía y col una lista con los valores de la columna "scores". Al iterar sobre el rango de la longitud de col de dos en dos, se puede ir añadiendo la suma de los valores de dos en dos.

print(output)

mostraría

[130, 178, 174]

Acceder a listas por valores combinados

Al atributo loc de un DataFrame te permite acceder a elementos específicos del DataFrame, por medio de valores booleanos. Esto permite localizar filas donde ciertas columnas cumplan ciertas condiciones.

lista = [df.loc[df["name"] == row] for row in set(df["name"])]

Cada valor de lista sería

     name degree  score
2  pankaj    MBA     80
3  pankaj    BCA     98

     name degree  score
0  aparna    MBA     90
1  aparna    BCA     40

     name degree  score
4  sudhir    MBA    101
5  sudhir    BCA     73

Se separan por el valor que tiene en la columna especificada, en este caso "name".

Quiero acceder a los valores de score a través de la combinación de name y degree.

Se puede generar una lista que contenga las filas que tienen en la columna "name" o "degree" individualmente por cada valor distinto.

filtered = [list(df.loc[df["name"] == row]["score"]) for row in sorted(set(df["name"]))]

Este expresión equivale a decir

El valor de la columna "score" en las filas que tengan como valor en la columna "name" cada valor en la columna "name".

Se usa:

  • list() para convetir los iterables de Pandas en listas
  • sorted(set()) para eliminar los nombres repetidos en la columna "name"

Esta expresión va a generar una lista con el valor de "score" de cada columna, valores separados en otros iterable por cada nombre diferente.

Por lo tanto

print(filtered[0][1])
print(filtered[1][1])
print(filtered[2][1])

mostraría

40
98
73

Espero te haya servido de algo.

Answered by user166844 on December 23, 2021

En pandas los métodos loc y iloc te permiten seleccionar los datos a partir de una columna por su etiqueta o por su índice en filas y columnas. Así que si quieres la primera fila puedes colocar df.iloc[0, 0] te imprimirla MBA, y df.iloc [0, :] toda la primera fila como una serie a la que podrás aplicarle sum ().

Answered by Luis Munoz on December 23, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP