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!
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
segunname
odegree
ya que son muchas tablas en excel y no las quiero poner cada una en listas.
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 :)
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]
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 listassorted(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
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP