Herramientas Computacionales

para la Investigación Interdisciplinaria Reproducible



  • Profesor: Dr. José Manuel Magallanes, PhD (jmagallanes@pucp.edu.pe)
    Profesor del Departamento de Ciencias Sociales, Pontificia Universidad Católica del Peru.
    Senior Data Scientist del eScience Institute and Visiting Professor at Evans School of Public Policy and Governance, University of Washington.
    Fellow Catalyst, Berkeley Initiative for Transparency in Social Sciences, UC Berkeley.

Sesión 2: Introducción al Python

Part A: Estructura de Datos en Python

Las estructuras de datos nos dicen como organizar y almacenar los datos que usamos. Tales estructuras van de lo simple a lo compuesto, y se les usa segun la necesidad particular. Veamos 4 de estas:

  1. Listas
  2. Tuplas
  3. Dictionarios
  4. Data Frames

Las Listas y tuplas son estructuras simples; un Data frame (DF) es una compuesta. Los dictionarios (tcc dicts) son estructuras versatiles a pesar de su simplicidad. Los DFs necesitan la instalación de librerías adicionales (no están en la base del Python).


Listas

Las listas contienen valores de cualquier tipo simple (numérico o no numérico), y podrían ser estructuras compuestas (lista de listas). Si usamos como referencia a una hoja de calculo con datos sobre individuos, una lista podria ser una fila que tiene los datos de los individuos.

In [2]:
DetailStudent=["Fred Meyers",40,"False"]

El object ‘DetailStudent’ almacena temporalmente la lista en la computadora. Los nombre pueden contener letras del alfabeto y números (y algunos caracteres de puntuación), pero no debe comenzar con un número.

En el código anterior, sólo se ha pedido crear la lista. Python lo ejecuta y nada más, no tienes que esperar ningún mensaje ni resultado. Si quieres ver lo que has creado, escribelo de manera explicita, así:

In [3]:
DetailStudent
Out[3]:
['Fred Meyers', 40, 'False']

Nota que hay varios tipos de datos en la lista:

  • FullName es texto o caracteres.
  • age es un numero.
  • female es un valor lógico.

Para acceder a cada uno de los elemento tu lista:

In [ ]:
DetailStudent[0] # primer elemento comienza con indice '0'
In [ ]:
DetailStudent[:2] # todo antes de índice 2 
In [ ]:
DetailStudent[-1] # ultimo elementos

Si quieres cambiar algun valor:

In [ ]:
DetailStudent[0]='Alfred Mayer'
DetailStudent

Para añadir elementos:

In [ ]:
DetailStudent.append('Seattle')

# Ahora tienes:
DetailStudent

Para borrar, se puede hacer por...

  • posición
  • valor

Así, ante estas listas:

In [ ]:
elementsA=[1,2,3,4] 
elementsB=[1,2,3,4] 

Then:

In [ ]:
## borrar tercer elemento
del elementsA[2]  
# luego:
elementsA  # 
In [ ]:
#  borrar valor '2'
elementsB.remove(2)
elementsB 

Si lo que querias era dejarlo vacío

In [ ]:
DetailStudent[3]=None
DetailStudent

Para eliminar la lista:

In [ ]:
newList=['a','b']
del newList
newList # becareful!... it is gone!

A veces queremos eliminar valores repetidos:

In [ ]:
weekdays=['M','T','W','Th','S','Su','Su']
weekdays

Para ello tenemos la función set:

In [ ]:
weekdays=list(set(weekdays))
weekdays

No hay vectores en Python?

Los vectores no son parte del modulo básico de Python, por lo que necesitan que llames a numpy (instálalo antes):

In [ ]:
import numpy as np

vector=np.array([1,'2',3])
vector # aquí hay coerción pues solo debe haber un tipo de datos

Los nombres de los vectores siguen las mismas reglas que para las listas.

Acceder a los elementos es igual que en listas:

In [ ]:
vector[1]
In [ ]:
vector[1]=1.5
vector

Por lo anterior, nótese que ya que el vector es de textos, se coercionará a texto cada valor numérico ingresado.

Para añadir elementos, también se usa append, pero algo diferente:

In [ ]:
vectora=np.array([1,2,3])
vectorb=np.array([1,2,'3'])
vectora=np.append(vectora,vectorb)
vectora

Para eliminar elementos:

In [ ]:
vectorc = np.array(['a','b','c','d'])
index = [1,2]

vectorc = np.delete(vectorc, index)
vectorc

También hay manera de eliminar valores duplicados:

In [ ]:
np.unique([1, 1, 22, 22, 333, 33])

Tuplas

Al principio parace que fueran listas:

In [ ]:
DetailStudentaTuple=("Fred Meyers",40,"False")

Para crearlas puedes usar '( )', el comando tuple() o nada:

In [ ]:
DetailStudentbTuple='Michael Nelson',60,'True'

La gran diferencia es que una vez creadas, ninguno de sus valores se puede modificar:

In [ ]:
# genera error
DetailStudentbTuple[1]=50

Los Dicts, superficialmente, son lo más similares a las listas de R:

In [ ]:
# creating dict:
DetailStudentDict={'fullName':"Fred Meyers",
               'age':40,
               'female':False}
# seeing it:
DetailStudentDict

Pero no tienen índices:

In [ ]:
DetailStudentDict[0]

Pare ver un elemento, tienes que saber el nombre de su campo ('key'):

In [ ]:
DetailStudentDict['age']

A partor de ahi, puedes hacer las operaciones comunes:

In [ ]:
DetailStudentDict['age']=81
DetailStudentDict

Listas versus Tuplas vs Dicts?

A) Aseguráte de saber qué tienes:

In [ ]:
type(DetailStudentDict)
In [ ]:
type(DetailStudent)
In [ ]:
type(DetailStudentaTuple)

B) Asegúrate que las funciones se pueden compartir

In [ ]:
listTest=[1,2,3,3]
tupleTest=(1,2,3,4,4)
dictTest={'a':1,'b':2,'c':2}
len(listTest), len(tupleTest), len(dictTest)

Ir a inicio


Data Frames

Los Data frames pueden interpretarse como estructuras compuestas en base a las simples. Python requiere que llamemos al pandas para usar DFs:

In [ ]:
# instálalo antes!
!pip install pandas

Ahora sí llamamos a Pandas:

In [ ]:
import pandas

# estas son columnas:

names=["Qing", "Françoise", "Raúl", "Bjork"]
ages=[32,33,28,30]
country=["China", "Senegal", "Spain", "Norway"]
education=["Bach", "Bach", "Master", "PhD"]
In [ ]:
# las llevamos a dict:
data={'names':names, 'ages':ages, 'country':country, 'education':education}

...y de dict a DF:

In [ ]:
students=pandas.DataFrame.from_dict(data)
# check it:
students

También podría ser a partir de filas:

In [ ]:
# Listas por fila
row1=["Qing", 32,"China", "Bach"]
row2=["Françoise", 33, "Senegal", "Bach"]
row3=["Raúl", 28, "Spain", "Master"]
row4=["Bjork", 30, "Norway", "PhD"]

#Lista de listas de filas
listOfRows=[row1,row2,row3,row4]

#creandolo:
DF_lists=pandas.DataFrame(listOfRows,columns=['names','ages','country','education'])
DF_lists

Tendremos un data frame? Recuerda que type te lo dice:

In [ ]:
type(students)

Pero Pandas da más detalles son 'dtypes':

In [ ]:
students.dtypes

Además de dtypes(), es bueno saber que puedes usar:

In [ ]:
# cuantas filas y columnas tienes:
students.shape # 

No hay función específica para saber cuantas filas o columnas hay independientemente, pero len ayuda:

In [ ]:
len(students.index) # or students.shape[0]
In [ ]:
len(students.columns) # or students.shape[1]

También son muy útiles las función head(), que te permite ver las filas al inicio del DF:

In [ ]:
students.head(2) 

Y su antónimo también está disponible:

In [ ]:
students.tail(2)

Claro que es bueno saber qué variables tenemos:

In [ ]:
students.columns

Lo anterior no es una lista, pero si la necesitas:

In [ ]:
list(students)

Tu DF es la tabla de datos a la que estás acostumbrado a utilizar. Si quieres ver algun elemento en particular:

In [ ]:
# una columna
students.names
In [ ]:
# or
students['names'] 
In [ ]:
# # varias columnas (con posiciones)
students.iloc[:,[1,3]]  
In [ ]:
# varias columnas (con nombres)
students[['country','education']]
In [ ]:
# varias columnas (con posiciones)
students.iloc[:,2:4]
In [ ]:
# una fila
students.iloc[2,]
In [ ]:
# varias filas
students.iloc[[2,3],]

Nótese en los casos anteriores, que si no indicabas filas, tenías toda la fila; y que si no indicas columnas, vienen todas las columnas. Si solo quieres un valor:

In [ ]:
students.iloc[1,3]

Es muy común, y necesario, crear subsets del DF:

In [ ]:
studentsNoEd=students.iloc[:,[0,1,2]]
studentsNoEd

Voy a hacer algunos cambios a este DF. Sin embargo, es común primero crear una copia del original:

In [ ]:
studentsCopy=students.copy()
studentsCopy

Ahora, a la copia le hago modificaciones.

In [ ]:
# cambio el valor de una edad:
studentsCopy.iloc[0,1]=23 # No hay advertencia, el cambio ya se hizo:
studentsCopy
In [ ]:
# Podemos tener una nueva columna con valores vacios
studentsCopy.country=None
studentsCopy
In [ ]:
# Y puedeo eliminar una columna:
studentsCopy.drop('ages',1,inplace=True) # axis=1 is column
studentsCopy

CONSULTAS en Data Frames:

Una de las primeras cosas que hacemos con los DF es hacerle consultas:

In [ ]:
# ¿Quién es el más viejo del grupo?
students[students.ages==max(students.ages)].names 
#students.loc[students['ages'].idxmax()].names
In [ ]:
# ¿Quién es el más joven del grupo?
students[students.ages==min(students.ages)].names 
#students.loc[students['ages'].idxmin()].names
In [ ]:
# ¿Quién tiene más de 30 y es de China?
students[(students.ages>30) & (students.country=='China')] # parentesis requeridos
In [ ]:
# ¿Quién no viene de Noruega?
students[students.country!="Norway"] 
In [ ]:
# ¿Quién no viene de estos lugares?

places=["China", "Spain"]
students[~students.country.isin(places)]
In [ ]:
# Muestrame el DF ordenado decrecientemente por edad**
toSort=["ages"]
Order=[False]
students.sort_values(by=toSort,ascending=Order)
In [ ]:
# Muestrame el DF ordenado crecientemente, por educacion y luego por edad

toSort=["education","ages"]
Order=[True,True]
students.sort_values(by=toSort,ascending=Order)

AUSPICIO:

El desarrollo de estos contenidos ha sido posible gracias al grant del Berkeley Initiative for Transparency in the Social Sciences (BITSS) at the Center for Effective Global Action (CEGA) at the University of California, Berkeley

RECONOCIMIENTO

El autor reconoce el apoyo que el eScience Institute de la Universidad de Washington le ha brindado desde el 2015 para desarrollar su investigación en Ciencia de Datos.