¡Esta es una revisión vieja del documento!
Pandas es una librería en cierto sentido similar a NumPy. Pero si NumPy únicamente contiene vectores, matrices, tensores ,etc junto con operaciones matemáticas. Con pandas tenemos mas cosas como nombrar a las columnas con un nombre , incluir un índices o generación de gráficas.
Mas información:
import pandas as pd
DataFrame
tipo=['SSD', 'SSD', 'SSD', 'SSD', 'SSD', 'SSD', 'SSD', 'SSD', 'SSD', 'SSD', 'SSD', 'SSD', 'SSD', 'SSD', 'SSD', 'HDD', 'HDD', 'HDD', 'HDD', 'HDD', 'HDD', 'HDD', 'HDD', 'HDD', 'HDD', 'HDD', 'HDD', 'HDD', 'HDD', 'HDD'] capacidad=[0.5, 0.5, 0.24, 0.48, 1, 0.512, 1, 0.48, 0.12, 0.96, 0.256, 0.512, 1, 2, 0.5, 2, 2, 1, 1.5, 4, 2, 4, 6, 5, 8, 10, 12, 14, 16, 18] precio=[101, 51, 27, 44, 86, 101, 138, 50, 22, 83, 41, 78, 126, 183, 91, 48, 51, 37, 55, 81, 48, 88, 187, 146, 240, 360, 387, 443, 516, 612] data=zip(tipo,capacidad,precio) columns=['tipo', 'capacidad','precio'] df=pd.DataFrame(data, columns=columns)
zip
es similar a np.column_stack
de numpy pero ha usado zip
en vez de column_stack
ya que hay datos de tipos string
. Si todos los datos hubieran sido números de podría haber usado column_stack
append
.
df=df.append({'tipo':"SSD","capacidad":1,"precio":214},ignore_index=True)
Mas información:
df.to_csv("datos.csv", index=False)
index=False
ya que sino creará en disco una columna extra con el nº de la fila a modo de índice
tipo,capacidad,precio SSD,0.5,101 SSD,0.5,51 SSD,0.24,27 SSD,0.48,44 ........ HDD,14.0,443 HDD,16.0,516 HDD,18.0,612 SSD,1.0,214
df=pd.read_csv("datos.csv",sep=",")
import sqlalchemy connection = sqlalchemy.create_engine('mysql+pymysql://mi_usuario:mi_contrasenya@localhost:3306/mi_database') df=pd.read_sql("SELECT * FROM mi_tabla",con=connection)
Crear un DataFrame desde una base de datos relacional es tan sencillo como crear la conexión con sqlalchemy.create_engine
y luego con pandas llamar a read_sql
.
conda install -c anaconda sqlalchemy
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 31 entries, 0 to 30 Data columns (total 3 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 tipo 31 non-null object 1 capacidad 31 non-null float64 2 precio 31 non-null int64 dtypes: float64(1), int64(1), object(1) memory usage: 872.0+ bytes
df.shape
(31, 3)
df.head()
tipo capacidad precio 0 SSD 0.50 101 1 SSD 0.50 51 2 SSD 0.24 27 3 SSD 0.48 44 4 SSD 1.00 86
df.tail()
tipo capacidad precio 26 HDD 12.0 387 27 HDD 14.0 443 28 HDD 16.0 516 29 HDD 18.0 612 30 SSD 1.0 214
df.describe()
capacidad precio count 31.000000 31.000000 mean 3.760000 152.741935 std 5.049022 153.423807 min 0.120000 22.000000 25% 0.506000 50.500000 50% 1.000000 88.000000 75% 4.500000 185.000000 max 18.000000 612.000000
df.corr()
capacidad precio capacidad 1.000000 0.949407 precio 0.949407 1.000000
Lo normal es que queramos acceder a los datos siempre por columnas. Así que explicaremos únicamente esa forma.
df['capacidad'] df.loc[:,'capacidad'] df.capacidad
loc
hay que indicar que queremos todas las filas para ello usamos el :
df[['precio','capacidad']] df.loc[:,['precio','capacidad']]
df.loc[:,df.columns!='tipo']
df df[:] df.loc[:,:]
df.iloc[:,1]
df.iloc[:,-1]
df.iloc[:,[0,-1]]
df.columns
['tipo', 'capacidad', 'precio']
len(df.columns)
df.columns[0]
rename
. Se pasa un diccionario cuya clave es el nombre actual y el valor es el nuevo nombre.
#Cambiamos el nombre de la columna "tipo" al nuevo nombre "target" df.rename(columns={'tipo': 'target'}, inplace=True) new_df=df.rename(columns={'tipo': 'target'})
inplace=True
se hace la modificación en el propio DataFrame
y no hace falta asignarlo a otro nuevo DataFrame
target
reindex
#Ahora la columna target está al final df=df.reindex(columns=['capacidad','precio','target'])
DataFrame
a un nuevo DataFrame
velocidad
al inicio del DataFrame
datos_nueva_columna=[1000, 1250, 6500, 2500, 2750, 2500, 1000, 1500, 2250, 5500, 2750, 4250, 5000, 3750, 2500, 6500, 5250, 5250, 3250, 3500, 7250, 6250, 2250, 3500, 4250, 6000, 2000, 3000, 5250, 2500] df.insert(0,"velocidad",datos_nueva_columna)
velocidad
antes del "precio"
datos_nueva_columna=[1000, 1250, 6500, 2500, 2750, 2500, 1000, 1500, 2250, 5500, 2750, 4250, 5000, 3750, 2500, 6500, 5250, 5250, 3250, 3500, 7250, 6250, 2250, 3500, 4250, 6000, 2000, 3000, 5250, 2500] df.insert(2,"velocidad",datos_nueva_columna)
df.insert(3,"calculada",df.precio*df.capacidad)
tipo capacidad precio calculada 0 SSD 0.50 101 50.50 1 SSD 0.50 51 25.50 2 SSD 0.24 27 6.48 3 SSD 0.48 44 21.12 4 SSD 1.00 86 86.00 ...........
calculada
df.drop(columns = ['calculada'], inplace = True) new_df=df.drop(columns = ['calculada'])
df[df.tipo=='SSD']
df[(df.tipo=='SSD') & (df.precio<100)]
DataFrame
así que se pueden aplicar todos los métodos de los DataFrame
.
df.tipo.unique()
array(['SSD', 'HDD'], dtype=object)
Vamos ahora a crear un DataFrame con datos inválidos.
tipo=[None, 'SSD', 'SSD', 'SSD', 'SSD', 'SSD', 'SSD', 'SSD', 'SSD', 'SSD', 'SSD', 'SSD', 'SSD', 'SSD', 'SSD', 'HDD', 'HDD', 'HDD', 'HDD', 'HDD', 'HDD', 'HDD', 'HDD', 'HDD', 'HDD', 'HDD', 'HDD', 'HDD', 'HDD', 'HDD'] capacidad=[0.5, float("NaN"), 0.24, 0.48, 1, 0.512, 1, 0.48, 0.12, 0.96, 0.256, 0.512, 1, 2, 0.5, 2, 2, 1, 1.5, 4, 2, 4, 6, 5, 8, 10, 12, 14, 16, 18] precio=[101, 51, float("NaN"), 44, 86, 101, 138, 50, 22, 83, 41, 78, 126, 183, 91, 48, 51, 37, 55, 81, 48, 88, 187, 146, 240, 360, 387, 443, 516, 612] data=zip(tipo,capacidad,precio) columns=['tipo', 'capacidad','precio'] df=pd.DataFrame(data, columns=columns)
null
de cada columna
df.isnull().sum()
tipo 0 capacidad 0 precio 0 dtype: int64
Con dataframes lo sencillo usar seaborn
figure=plt.figure(figsize=(12,8)) axes = figure.add_subplot() sns.scatterplot(x="capacidad", y="precio", hue="tipo",data=df,ax=axes)
figure=plt.figure(figsize=(16,5)) axes = figure.add_subplot(1,2,1) sns.kdeplot(x="capacidad",data=df,fill=True,ax=axes) axes = figure.add_subplot(1,2,2) sns.kdeplot(x="precio",data=df,fill=True,ax=axes)
figure=plt.figure(figsize=(16,5)) axes = figure.add_subplot(1,2,1) sns.kdeplot(x="capacidad",hue="tipo",data=df,fill=True,ax=axes) axes = figure.add_subplot(1,2,2) sns.kdeplot(x="precio",hue="tipo",data=df,fill=True,ax=axes)
figure=plt.figure(figsize=(16,5)) axes = figure.add_subplot(1,2,1) sns.histplot(x="capacidad",hue="tipo",data=df,ax=axes) axes = figure.add_subplot(1,2,2) sns.histplot(x="precio",hue="tipo",data=df,ax=axes)
pairplot=sns.pairplot(df,hue="tipo")
Genera un HTML con información del DataFrame
from pandas_profiling import ProfileReport reporte = ProfileReport(df, title = "Mi reporte") reporte.to_file("reporte.html")
Se puede ver el resultado en pandas_profiling.html
Mas información: