Una tabla de columnas etiquetadas
Un DataFrame es una tabla bidimensional: un conjunto de columnas, cada una una Series, que comparten un índice de etiquetas de fila. Es el caballo de batalla del análisis de datos de mercado: una fila por símbolo o por día, una columna por campo (precio, volumen, rendimiento). Se construye a partir de un diccionario de columnas, pd.DataFrame({"price": [...], "volume": [...]}, index=symbols), o de una lista de diccionarios de filas. Cada columna tiene su propio dtype (los precios son float64, los volúmenes int64), a diferencia de un arreglo NumPy que tiene un único dtype para todo.
import pandas as pd
df = pd.DataFrame(
{"price": [184.25, 410.2, 171.0], "volume": [200, 50, 300]},
index=["AAPL", "MSFT", "GOOG"],
)
print(df)
# price volume
# AAPL 184.25 200
# MSFT 410.20 50
# GOOG 171.00 300
print(df.shape, df.columns.tolist()) # (3, 2) ['price', 'volume']
print(df.dtypes.astype(str).to_dict()) # {'price': 'float64', 'volume': 'int64'}
rows = [{"symbol": "AAPL", "price": 184.25}, {"symbol": "MSFT", "price": 410.2}]
print(pd.DataFrame(rows)) # from a list of row dictionaries
# symbol price
# 0 AAPL 184.25
# 1 MSFT 410.20Columnas, columnas nuevas y filas filtradas
df["price"] es una columna, una Series; df[["price"]] con una lista es un DataFrame de una columna. Una columna nueva sale de aritmética entre columnas: df.assign(notional=df["price"] * df["volume"]) devuelve un marco nuevo con la columna extra y deja df intacto (escribir df["notional"] = ... modifica el propio df). Una condición booleana sobre una columna filtra filas, df[df["volume"] >= 100], y df.sort_values("volume", ascending=False) las ordena, con .head(n) quedándose con las primeras n. Todo esto opera sobre columnas enteras a la vez: no recorras filas con iterrows() cuando existe una operación de columna.
import pandas as pd
df = pd.DataFrame(
{"price": [184.25, 410.2, 171.0], "volume": [200, 50, 300]},
index=["AAPL", "MSFT", "GOOG"],
)
bigger = df.assign(notional=df["price"] * df["volume"]) # a new frame
print(bigger)
# price volume notional
# AAPL 184.25 200 36850.0
# MSFT 410.20 50 20510.0
# GOOG 171.00 300 51300.0
print(df.columns.tolist()) # ['price', 'volume'] df is unchanged
print(df[df["volume"] >= 100]) # rows that pass the test
# price volume
# AAPL 184.25 200
# GOOG 171.00 300
print(df.sort_values("volume", ascending=False).head(2)) # the two biggest volumes
# price volume
# GOOG 171.00 300
# AAPL 184.25 200Resúmenes y una mirada a los datos
Mira siempre una tabla antes de fiarte de ella. df.head() muestra las primeras filas, df.shape da (filas, columnas), df.dtypes lista el tipo de cada columna, df.isna().sum() cuenta los valores ausentes por columna y df.describe() resume las columnas numéricas (cuenta, media, desviación típica, mínimo, cuartiles, máximo). Los métodos de columna como df.mean() dan un valor por columna; df.sum(axis=1) da uno por fila. Un dtype object o str donde esperabas números suele significar que se coló texto en la columna.
import pandas as pd
df = pd.DataFrame(
{"price": [184.25, 410.2, 171.0], "volume": [200, 50, 300]},
index=["AAPL", "MSFT", "GOOG"],
)
print(df.describe().loc[["count", "mean", "max"]])
# price volume
# count 3.00 3.000000
# mean 255.15 183.333333
# max 410.20 300.000000
print(df.mean().to_dict()) # {'price': 255.15, 'volume': 183.33333333333334}
print(df.sum(axis=1).tolist()) # [384.25, 460.2, 471.0] one value per row
print(df.isna().sum().to_dict()) # {'price': 0, 'volume': 0}
# Changing a copy never changes the original (pandas 3 copies on write)
cheap = df[df["price"] < 200].copy()
cheap.loc["AAPL", "price"] = 0.0
print(df.loc["AAPL", "price"]) # 184.25import pandas as pd
rows = [
{"symbol": "AAPL", "price": 184.25, "volume": 200},
{"symbol": "MSFT", "price": 410.2, "volume": 50},
]
df = pd.DataFrame(rows).set_index("symbol") # make a column the row labels
print(df)
# price volume
# symbol
# AAPL 184.25 200
# MSFT 410.20 50
print(df.rename(columns={"price": "px"}).columns.tolist()) # ['px', 'volume']
print(df.drop(columns="volume").columns.tolist()) # ['price']
print(df.reset_index().columns.tolist()) # ['symbol', 'price', 'volume']assign, el filtrado booleano y sort_values, que devuelven marcos nuevos. El error clásico es escribir una columna nueva en el argumento, lo que la añade en silencio a la tabla de quien llama. Las pruebas del lab comparan el argumento antes y después justo por eso.pd.DataFrame({columna: valores}, index=labels);df["c"]es una Series,df[["c"]]un DataFrame; cada columna tiene su dtype.assignañade una columna a un marco nuevo;df[máscara]filtra filas;sort_values(...).head(n)toma los n primeros.- Mira primero:
shape,dtypes,head(),describe(),isna().sum(); nunca edites el marco de quien llama.
A continuación: seleccionar datos con loc e iloc, las dos formas precisas de elegir filas y columnas por etiqueta o por posición.
Lab: qué se califica
- Construir una tabla de precios y volúmenes con
make_frame25 pts - Añadir una columna de valor negociado con
add_notional25 pts - Quedarse solo con las filas líquidas con
filter_liquid25 pts - Clasificar las filas por cualquier columna con
top_by25 pts