90UBA XXI, cátedra Balbiano

Pensamiento Computacional

UBA XXI · Cátedra Balbiano · Teoría completa de las 6 unidades
Primer parcial Unidades 1-4 (parte 1)
1 Introducción a la programación y Python

¿Qué es la programación?

La programación es la actividad de escribir instrucciones precisas que una computadora puede ejecutar para resolver un problema. La computadora es muy rápida pero completamente literal: hace exactamente lo que vos le decís, ni más ni menos. Si le decís algo ambiguo o mal, va a hacer cualquier cosa o tirar error.

Programar consiste en traducir una idea o procedimiento humano a un lenguaje que la computadora entienda. El "lenguaje" en este caso es un lenguaje de programación. En esta materia vas a usar Python.

¿Qué es un algoritmo?

Un algoritmo es una secuencia finita y ordenada de pasos para resolver un problema. La palabra clave es "preciso": cada paso debe ser entendible y ejecutable sin ambigüedad.

Un algoritmo puede existir sin computadoras: una receta de cocina, las instrucciones para armar un mueble, los pasos para resolver una cuenta a mano. Todos son algoritmos.

Algoritmo cotidiano
Hacer un café:
1. Poner agua en la pava.
2. Encender el fuego.
3. Esperar a que hierva.
4. Poner café en la taza.
5. Echar el agua caliente.

Si seguís los pasos en orden, obtenés café.
Algoritmo numérico
Saber si un número es par:
1. Tomar el número.
2. Dividirlo por 2.
3. Si el resto es 0, decir "es par". Si no, decir "es impar".

¿Qué es un programa?

Un programa es un algoritmo escrito en un lenguaje de programación. Cuando programás, lo que hacés es:

  1. Pensar el algoritmo (en español, en pseudocódigo, o con un esquema).
  2. Traducirlo al código del lenguaje (Python, en este caso).
  3. Ejecutarlo en la computadora para verificar que funcione.

Python: características clave

Python es uno de los lenguajes más populares del mundo. Tiene tres ventajas que lo hacen ideal para empezar:

  • Sintaxis legible: el código se parece bastante al inglés y es fácil de leer.
  • Interpretado: no hace falta "compilar". La máquina ejecuta el código línea por línea al instante.
  • Universal: se usa para ciencia de datos, IA, web, ingeniería, finanzas y mucho más.
print("Hola, mundo")

Este es el programa más chico que vas a escribir. La función print() muestra en pantalla el contenido entre paréntesis. En este caso, muestra el texto Hola, mundo.

Google Colab: dónde escribir y ejecutar Python

Para esta materia vas a usar Google Colab: un entorno web (no necesitás instalar nada) donde escribís y ejecutás Python. Lo abrís desde el navegador con tu cuenta de Google.

Colab en 30 segundos
• Cada notebook se compone de celdas.
• Las celdas pueden ser de código (Python) o de texto (Markdown, para anotaciones).
• Para ejecutar una celda: Shift + Enter. La computadora corre el código y muestra el resultado abajo.
• Las variables y funciones que definís en una celda quedan disponibles en las siguientes (siempre que no reinicies el entorno).

Variables

Una variable es un nombre que guarda un valor. La analogía clásica es la de una caja etiquetada: la etiqueta es el nombre, el contenido es el valor. Lo que metés en la caja es lo que la variable "vale".

edad = 25
nombre = "Bruno"
pi = 3.14159

print(edad)
print(nombre)
print(pi)

Después de esas líneas, "edad" vale 25, "nombre" vale el texto "Bruno", y "pi" vale 3.14159.

El signo = es asignación, NO igualdad

En matemática, "x = 5" significa "x es igual a 5". En programación, x = 5 significa "asigna el valor 5 a la variable x". Es una orden, no una afirmación.

Por eso esto, que en matemática sería raro, es perfectamente válido en Python:

x = 10
x = x + 5     # toma el valor actual de x (10), le suma 5, y lo guarda de nuevo en x
print(x)      # 15
Reglas para nombres de variables
• Pueden tener letras, números y guion bajo _.
• NO pueden empezar con número: 2edad ❌
• NO pueden tener espacios: edad_actual ✓, edad actual ❌
• Acentos y ñ: Python 3 los acepta (año = 2026 funciona), pero la costumbre es evitarlos y escribir anio, para no tener problemas al pasar el código de una máquina a otra.
• Distinguen mayúsculas: Edad y edad son variables distintas.
• No pueden ser palabras reservadas de Python: if, while, for, def, True, etc.
• Tampoco conviene pisar funciones que ya existen: print, len, list o input no son palabras reservadas, así que Python te deja escribir print = 5, pero después print("hola") deja de funcionar.
• Convención: elegí nombres descriptivos en minúsculas con guion_bajo. total_pagado es mucho mejor que x.

Tipos primitivos (vista previa)

Cada valor en Python tiene un tipo. Los más comunes son:

  • Entero (int): números sin coma. 5, -3, 0, 1000.
  • Real (float): números con coma. 3.14, -0.5, 2.0.
  • Cadena (str): texto, siempre entre comillas. "hola", 'Python'.
  • Booleano (bool): verdadero o falso. True, False.

En la unidad 2 los vemos con detalle. Por ahora, lo importante: "123" no es lo mismo que 123. El primero es texto, el segundo es número.

print() en detalle

print() muestra cosas en pantalla. Se le puede pasar:

  • Un solo valor: print(42) o print("hola").
  • Varios separados por comas: print("Edad:", 25) imprime Edad: 25.
  • Variables o expresiones: print(x + 1).
Ejemplos
a = 5
b = 3
print("Suma:", a + b)        # Suma: 8
print("Mitad:", a / 2)       # Mitad: 2.5
print("Hola", "Mundo")       # Hola Mundo (los separa con espacio)

f-strings (formato de texto)

Para insertar variables dentro de un texto de manera elegante:

nombre = "Bruno"
edad = 30
print(f"Hola {nombre}, tenés {edad} años")
# Hola Bruno, tenés 30 años

Empezás con f" (o f') y dentro del texto, lo que va entre { } se reemplaza por el valor de la variable.

El intérprete de Python

Python es un lenguaje interpretado: la computadora lee el código línea por línea y lo ejecuta al momento. Eso es distinto de los lenguajes compilados (como C o C++) donde primero se traduce todo a un ejecutable y después se corre.

Ventaja de interpretado: probás cosas rápido. En Colab, cada celda es un bloque que ejecutás con Shift+Enter y ves el resultado al instante.

Comentarios

Los comentarios son texto que Python ignora. Sirven para explicar qué hace el código, dejar notas para vos o para quien lo lea.

# Esto es un comentario de una línea
x = 5   # también puede ir al final de una línea de código

# Para comentarios largos podés
# usar varias líneas con # cada una
¿Cuándo comentar?
• Para explicar el "por qué" de algo no obvio.
• Para marcar secciones de código largo.
• Para "desactivar" temporalmente una línea sin borrarla.
NO comentes lo obvio: x = 5 # asignamos 5 a x es ruido.
Errores típicos al empezar
• Olvidar las comillas en los textos: nombre = Bruno ❌ (sin comillas Python busca una variable llamada Bruno y tira NameError). Lo correcto: nombre = "Bruno".
• Confundir = con ==: el primero asigna, el segundo compara.
• Olvidar los paréntesis de print: print "hola" ❌ (esa era sintaxis de Python 2). Siempre con paréntesis.
• Mezclar tipos sin convertir: print("Edad: " + 25) ❌. Tenés que hacer print("Edad: " + str(25)) o usar print("Edad:", 25).
• Escribir el mismo nombre de dos maneras: si definís anio = 2026 y después usás año o Anio, Python tira NameError, porque para él son variables distintas.
↑ Volver al índice
2 Tipos de datos, expresiones y funciones

Tipos de datos primitivos

Cada valor en Python tiene un tipo que determina qué operaciones podés hacer con él. Los cuatro tipos primitivos son:

TipoNombreEjemplosSirve para
Enteroint7, -3, 0, 1000Conteos, índices, valores discretos
Real (decimal)float3.14, -0.5, 2.0Medidas, promedios, valores con coma
Cadenastr"hola", 'Python'Textos, etiquetas, mensajes
BooleanoboolTrue, FalseVerdadero/falso, decisiones
Detalles importantes
• Decimales con punto, no coma: en Python se escribe 3.14, no 3,14.
• Strings con comillas: simples ('hola') o dobles ("hola"). Son equivalentes. Tenés que abrir y cerrar con el mismo tipo.
• Booleanos en mayúscula: True y False con T y F mayúsculas. true ❌ no funciona.

La función type()

Te dice el tipo de un valor o variable:

type(5)        # <class 'int'>
type(3.14)     # <class 'float'>
type("hola")   # <class 'str'>
type(True)     # <class 'bool'>

x = 7.5
print(type(x))  # <class 'float'>

Conversiones de tipo (casting)

A veces necesitás convertir un valor de un tipo a otro. Las funciones de conversión se llaman como el tipo destino:

FunciónConvierte aEjemplos
int(x)Enteroint("123") → 123, int(3.7) → 3 (trunca)
float(x)Realfloat("3.14") → 3.14, float(5) → 5.0
str(x)Cadenastr(42) → "42", str(3.14) → "3.14"
bool(x)Booleanobool(0) → False, bool(1) → True
Ojo con int()
int(3.7) da 3, NO 4: trunca (corta los decimales), no redondea. Si querés redondear usá round(3.7) que da 4.
También cuidado: int("3.14") ❌ tira error. Para texto con decimales primero hay que pasar a float: int(float("3.14")) → 3.

Operadores aritméticos

OperadorSignificadoEjemploResultado
+Suma5 + 38
-Resta5 - 32
*Multiplicación5 * 315
/División (siempre da float)10 / 33.333...
//División entera (cociente)10 // 33
%Módulo (resto)10 % 31
**Potencia2 ** 38
El operador módulo % · súper útil
Devuelve el resto de la división entera. Casos típicos:
• n % 2 == 0 ⇒ n es par.
• n % 2 == 1 ⇒ n es impar.
• n % 5 == 0 ⇒ n es múltiplo de 5.
• En general: n % k == 0 ⇒ n es múltiplo de k.
Diferencia entre / y //
10 / 3     # 3.333333333... (float)
10 // 3    # 3              (entero, descarta decimales)
10 % 3     # 1              (resto)

# Verificación: cociente * divisor + resto = dividendo
3 * 3 + 1  # 10 ✓

Precedencia de operadores

Como en matemática, hay un orden de prioridad:

  1. Paréntesis: lo de adentro primero.
  2. Potencia **.
  3. Multiplicación, división (*, /, //, %), todas al mismo nivel.
  4. Suma, resta (+, -), al mismo nivel.

En cada nivel, se evalúa de izquierda a derecha. Si dudás del orden, usá paréntesis: hace el código más legible y evita errores.

Ejemplos
2 + 3 * 4         # 14 (no 20: primero la multiplicación)
(2 + 3) * 4       # 20
2 ** 3 + 1        # 9 (primero potencia)
10 - 3 - 2        # 5 (10-3=7, 7-2=5: izquierda a derecha)

Operadores con strings

Algunos operadores funcionan también con texto:

"hola" + " " + "mundo"   # "hola mundo" (concatenación)
"abc" * 3                # "abcabcabc" (repetición)
"hola"[0]                # "h" (primer carácter)
len("hola")              # 4 (longitud)
No podés mezclar tipos sin convertir
"Edad: " + 25 ❌ tira TypeError porque mezcla str e int. Soluciones:
• Convertir: "Edad: " + str(25)
• Usar print con coma: print("Edad:", 25)
• Usar f-string: f"Edad: {25}"

Métodos de strings

Un método es una función que se le pide al texto con un punto: texto.metodo(). Los strings son inmutables: ningún método cambia el texto original, todos devuelven un texto nuevo.

MétodoQué haceEjemplo
upper() / lower()Pasa todo a mayúsculas / minúsculas"hola".upper() → "HOLA"
replace(viejo, nuevo)Cambia todas las apariciones"banana".replace("a", "o") → "bonono"
count(x)Cuántas veces aparece"banana".count("a") → 3
find(x)Posición de la primera aparición (−1 si no está)"banana".find("n") → 2
strip()Saca espacios y saltos de línea de las puntas" hola \n".strip() → "hola"
split(sep)Corta el texto y devuelve una lista. Sin argumento corta por espacios"a,b,c".split(",") → ['a', 'b', 'c']
sep.join(lista)Lo contrario de split: une una lista de textos"-".join(["a", "b", "c"]) → "a-b-c"
isalpha() / isdigit()¿Son todas letras? / ¿son todos dígitos?"abc1".isalpha() → False
texto = "Hola Mundo"
texto.upper()               # devuelve "HOLA MUNDO", pero no lo guardé
print(texto)                # Hola Mundo (el original no cambió)

texto = texto.upper()       # ahora sí lo guardo
palabras = texto.split()    # ['HOLA', 'MUNDO']
print("_".join(palabras))   # HOLA_MUNDO
El error que más se toma
Escribir texto.upper() o texto.replace("a", "o") en una línea suelta no cambia la variable. Si el programa no reasigna (texto = texto.upper()), el texto sigue igual que antes.

Operadores relacionales (comparación)

Comparan valores y siempre devuelven un booleano (True o False).

OperadorSignificadoEjemploResultado
==Igual a5 == 5True
!=Distinto de5 != 3True
<Menor que3 < 5True
>Mayor que3 > 5False
<=Menor o igual5 <= 5True
>=Mayor o igual5 >= 6False
El error más frecuente del mundo
Confundir = con ==:
• = es asignación: "poner el valor de la derecha en la variable de la izquierda".
• == es comparación: "¿son iguales?"
Si en una condición usás = en lugar de ==, tirás error de sintaxis.

Operadores lógicos

Combinan booleanos para hacer condiciones más complejas. Son and, or y not (en inglés).

Tablas de verdad

ABA and BA or Bnot A
TrueTrueTrueTrueFalse
TrueFalseFalseTrueFalse
FalseTrueFalseTrueTrue
FalseFalseFalseFalseTrue
  • and: verdadero si ambos son verdaderos. Si uno solo es falso, el resultado es falso.
  • or: verdadero si al menos uno es verdadero. Solo es falso si los dos son falsos.
  • not: invierte. not True es False, not False es True.
Ejemplos
edad = 20
tiene_dni = True

# ¿Puede votar? Tiene que tener edad >= 16 Y tener DNI.
puede_votar = edad >= 16 and tiene_dni
print(puede_votar)   # True

# ¿Es menor o jubilado?
es_menor_o_jubilado = edad < 18 or edad >= 65
print(es_menor_o_jubilado)   # False

# ¿NO tiene edad?
print(not (edad >= 18))      # False (sí tiene)
Combinaciones útiles
• "x está entre 1 y 10": 1 <= x and x <= 10. Python también permite la forma elegante 1 <= x <= 10.
• "x es vocal": x == "a" or x == "e" or x == "i" or x == "o" or x == "u". Más corto: x in "aeiou".
• "x es par y positivo": x % 2 == 0 and x > 0.

Entrada del usuario: input()

La función input() pide datos al usuario y los devuelve como texto.

nombre = input("¿Cómo te llamás? ")
print("Hola,", nombre)

El argumento de input() es el "cartel" o prompt que se muestra. Lo que el usuario escribe se guarda en la variable.

¡La trampa más típica del parcial!
input() siempre devuelve un string, incluso si el usuario escribe un número.

Si pedís edad = input("Edad: ") y el usuario escribe 25, la variable vale el string "25", no el número 25. Si querés operar con él (sumarle, compararlo numéricamente), tenés que convertir:
edad = int(input("Edad: ")) (para enteros)
peso = float(input("Peso: ")) (para decimales)

Funciones

Una función es un bloque de código con nombre que hace una tarea específica. Es como una "mini-máquina" reutilizable: la definís una vez, la podés usar cuántas veces quieras.

¿Por qué usar funciones?

  • Reutilización: escribís la lógica una vez y la llamás muchas.
  • Claridad: el código se vuelve más legible si está organizado en funciones con nombres descriptivos.
  • Testeo: podés probar cada función por separado.

Sintaxis

def nombre_funcion(parametros):
    # código de la función (indentado)
    return resultado
Ejemplo simple
def doble(x):
    return x * 2

print(doble(5))    # 10
print(doble(7))    # 14
print(doble(-3))   # -6

# La función se evalúa cada vez que la llamás
total = doble(10) + doble(20)
print(total)       # 60

Partes de una función

PartePara qué sirve
defPalabra clave que indica que vas a definir una función.
nombreEl identificador con el que la vas a llamar después. Mismas reglas que las variables.
parámetrosLos datos que la función recibe (entre paréntesis). Pueden ser varios separados por comas, o ninguno.
cuerpoLas líneas indentadas debajo (con 4 espacios o un tab). La indentación es obligatoria.
returnDevuelve el resultado al lugar donde se llamó la función. Si no hay return, devuelve None.

Parámetros vs argumentos

  • Parámetro: el nombre que aparece en la definición. def doble(x) tiene parámetro x.
  • Argumento: el valor concreto que pasás cuando la llamás. doble(5) tiene argumento 5.

Funciones con múltiples parámetros

def sumar(a, b):
    return a + b

def area_rectangulo(base, altura):
    return base * altura

print(sumar(3, 7))               # 10
print(area_rectangulo(5, 4))     # 20

Funciones sin return

Si una función no tiene return, simplemente ejecuta sus instrucciones y devuelve None (que es la "nada" de Python). Se usa cuando la función no necesita devolver un valor pero hace algo útil (imprimir, modificar algo, etc.).

def saludar(nombre):
    print(f"Hola {nombre}!")

saludar("Bruno")    # imprime "Hola Bruno!"
x = saludar("Ana")  # imprime "Hola Ana!" y x queda con None
Diferencia: print vs return
• print muestra en pantalla (visible para el usuario), pero la función no devuelve nada útil.
• return devuelve un valor a quien llamó la función, para que pueda usarlo (asignarlo a una variable, sumarlo, etc.).
Si solo imprimís y no devolvés, no podés "usar" el resultado en cálculos posteriores.

Variables locales y globales

Las variables definidas dentro de una función son locales: solo existen ahí adentro. Cuando la función termina, desaparecen.

def calcular():
    x = 10        # x es local
    return x * 2

resultado = calcular()
print(resultado)    # 20
# print(x)          # ❌ NameError: x no existe acá afuera

Indentación: lo más importante de Python

CRÍTICO
A diferencia de otros lenguajes (C, JavaScript, etc.) que usan { }, Python usa la indentación (los espacios al principio de la línea) para marcar qué código está "dentro" de una función, un if, un ciclo, etc.

Reglas:
• Siempre usá la misma cantidad de espacios para el mismo nivel (4 es el estándar).
• NO mezcles tabs y espacios: Python tira error.
• En Colab, podés usar Tab y se convierten automáticamente a 4 espacios.
• Una función o bloque indentado debe tener al menos una línea adentro.

Templates de funciones típicas

Función que devuelve un booleano
def es_par(n):
    return n % 2 == 0

print(es_par(4))   # True
print(es_par(7))   # False
Función que valida algo
def es_vocal(letra):
    return letra in "aeiouAEIOU"

print(es_vocal("a"))    # True
print(es_vocal("z"))    # False
Función que devuelve varios valores (con tupla)
def division_y_resto(a, b):
    return a // b, a % b

c, r = division_y_resto(13, 4)
print(c, r)    # 3 1
Errores típicos en funciones
• Olvidar los dos puntos : al final del def.
• No indentar el cuerpo.
• Usar print en vez de return cuando se necesita el valor.
• Llamar la función con menos argumentos que los parámetros declarados.
• Olvidar el return y después intentar usar el resultado.
↑ Volver al índice
3 Estructuras de control

¿Qué son las estructuras de control?

Por defecto, Python ejecuta el código de arriba hacia abajo, línea por línea. Las estructuras de control cambian ese flujo:

  • Condicionales (if, elif, else): ejecutan código según una condición.
  • Ciclos (while, for): repiten código múltiples veces.

Condicional: if

Ejecuta un bloque solo si se cumple una condición.

if edad >= 18:
    print("Sos mayor de edad")

Si la condición edad >= 18 es verdadera, ejecuta el bloque indentado. Si es falsa, no hace nada y sigue con lo que viene después.

if / else

"Si se cumple X, hacé una cosa; si no, hacé otra".

if edad >= 18:
    print("Mayor de edad")
else:
    print("Menor de edad")

Una de las dos ramas se ejecuta, nunca las dos.

if / elif / else

Para varias opciones encadenadas. elif es contracción de "else if":

nota = 7

if nota >= 8:
    print("Muy bien")
elif nota >= 6:
    print("Bien")
elif nota >= 4:
    print("Aprobado")
else:
    print("Desaprobado")
Cómo funciona la cadena
Python evalúa las condiciones en orden de arriba hacia abajo. Cuando encuentra una verdadera, ejecuta solo ese bloque y salta todo el resto. El else se ejecuta solo si ninguna anterior fue cierta.

En el ejemplo de arriba, con nota = 7:
1. ¿7 >= 8? No.
2. ¿7 >= 6? Sí ⇒ imprime "Bien" y termina.
3. Las demás condiciones ni se evalúan.

El orden importa

Si invertís las condiciones, el resultado cambia:

nota = 7

if nota >= 4:        # ❌ MAL: este sería el primer match
    print("Aprobado")
elif nota >= 6:
    print("Bien")
elif nota >= 8:
    print("Muy bien")

Acá nunca llegaría a "Bien" o "Muy bien" porque el primer if ya capturó toda nota ≥ 4. Empezá siempre por las condiciones más estrictas.

Condiciones compuestas

edad = 25
tiene_dni = True

if edad >= 18 and tiene_dni:
    print("Puede votar")

# Múltiples opciones
dia = "lunes"
if dia == "sábado" or dia == "domingo":
    print("Es fin de semana")
else:
    print("Es día de semana")

Condicionales anidados

Un if adentro de otro:

if tiene_dni:
    if edad >= 16:
        print("Puede votar")
    else:
        print("Muy joven para votar")
else:
    print("Necesita DNI")

Esto es equivalente a usar and en muchos casos, pero te permite tomar decisiones distintas en cada nivel.

Errores típicos en condicionales
• Olvidar los dos puntos : al final de la condición.
• Olvidar la indentación del bloque interno.
• Usar = en vez de ==: if x = 5: ❌ tira error.
• Comparar mal strings: if dia = "lunes": ❌, if dia == "lunes": ✓.

Ciclo while

Repite un bloque de código mientras se cumpla una condición. Cada repetición se llama iteración.

i = 0
while i < 5:
    print(i)
    i = i + 1

Imprime 0, 1, 2, 3, 4. El ciclo sigue mientras i < 5. En cada vuelta se suma 1, hasta que i llega a 5 y la condición se vuelve falsa.

Patrón "contador"

i = 0
while i < n:    # n veces
    # hacer algo
    i = i + 1

Patrón "validación de entrada"

n = int(input("Ingresá un positivo: "))
while n <= 0:
    print("Tiene que ser positivo")
    n = int(input("Ingresá un positivo: "))

Sigue pidiendo hasta que el usuario ingrese algo válido.

Patrón "bandera"

seguir = True
while seguir:
    respuesta = input("¿Continuar? (s/n): ")
    if respuesta == "n":
        seguir = False
    else:
        print("Hacemos otra cosa...")

Patrón "acumulador"

suma = 0
i = 1
while i <= 100:
    suma = suma + i
    i = i + 1
print(suma)    # 5050 (suma de 1 a 100)
Casos de uso típicos de while
• Validar datos: "pedir un número hasta que sea positivo".
• Repetir hasta una señal: "jugar hasta que el usuario diga que basta".
• No sabés cuántas veces: "leer un archivo hasta el final", "esperar hasta que pase algo".
¡Cuidado con los ciclos infinitos!
Si la condición nunca se hace falsa, el ciclo no termina nunca. Asegurate de que algo dentro del ciclo modifica la variable de la condición.

Ciclo infinito clásico:
i = 0
while i < 5:
    print(i)
    # ❌ falta i = i + 1, i nunca llega a 5
En Colab, si te queda un ciclo infinito: pulsá el ▢ (cuadrado) o "Interrumpir ejecución".

Ciclo for

Recorre los elementos de una secuencia (lista, string, range, tupla, diccionario...) uno por uno.

for letra in "Python":
    print(letra)

Imprime P, y, t, h, o, n.

nombres = ["Ana", "Bruno", "Carla"]
for nombre in nombres:
    print("Hola", nombre)

La función range()

Genera una secuencia de enteros. Muy usada con for:

FormaGenera
range(5)0, 1, 2, 3, 4 (cinco valores empezando desde 0)
range(2, 7)2, 3, 4, 5, 6 (de 2 a 6)
range(0, 10, 2)0, 2, 4, 6, 8 (paso de 2)
range(10, 0, -1)10, 9, 8, ..., 1 (cuenta regresiva)
range(1, 11)1, 2, 3, ..., 10
REGLA DE ORO: range NO incluye el extremo final
range(5) va de 0 a 4, no incluye el 5.
range(2, 7) va de 2 a 6, no incluye el 7.
Si querés que llegue hasta n inclusive, escribí range(n+1) o range(1, n+1).
Sumar los primeros 10 números
suma = 0
for i in range(1, 11):    # 1, 2, ..., 10
    suma = suma + i
print(suma)   # 55
Imprimir tabla del 5
for i in range(1, 11):
    print(f"5 x {i} = {5 * i}")
Recorrer una lista por elemento e índice (enumerate)
colores = ["rojo", "verde", "azul"]
for i, color in enumerate(colores):
    print(f"{i}: {color}")
# 0: rojo
# 1: verde
# 2: azul

¿Cuándo for y cuándo while?

Usá for cuando...Usá while cuando...
Sabés cuántas veces vas a iterarNo sabés a priori cuántas veces
Recorrés una secuencia conocida (lista, string, range)Esperás a que algo pase (input válido, fin de archivo)
Contás de n a mValidás entrada del usuario
Ejemplo: imprimir una tablaEjemplo: pedir clave hasta que sea correcta

break y continue

  • break: corta el ciclo inmediatamente, sale de él.
  • continue: salta a la siguiente iteración sin ejecutar el resto del cuerpo.
for i in range(10):
    if i == 5:
        break       # corta al llegar a 5
    print(i)
# Imprime 0, 1, 2, 3, 4 (no llega a 5)
for i in range(10):
    if i % 2 == 0:
        continue    # salta los pares
    print(i)
# Imprime 1, 3, 5, 7, 9

Ciclos anidados

Un ciclo dentro de otro. Útil para recorrer estructuras de dos dimensiones:

for i in range(1, 4):
    for j in range(1, 4):
        print(f"{i},{j}", end=" ")
    print()
# 1,1 1,2 1,3
# 2,1 2,2 2,3
# 3,1 3,2 3,3
Tabla de multiplicar completa
for i in range(1, 11):
    for j in range(1, 11):
        print(f"{i*j:4}", end="")
    print()
↑ Volver al índice
4 Listas y tuplas

¿Qué es una lista?

Una lista es una colección ordenada y mutable de elementos. "Ordenada" porque cada elemento ocupa una posición específica. "Mutable" porque podés modificarla después de crearla.

numeros = [10, 20, 30, 40, 50]
palabras = ["casa", "árbol", "auto"]
mezcla = [1, "hola", 3.14, True]   # puede tener distintos tipos
vacia = []                          # lista vacía

Acceso por índice

Los elementos se acceden por su índice, que en Python empieza desde 0 (NO desde 1).

numeros = [10, 20, 30, 40, 50]
print(numeros[0])   # 10 (primero)
print(numeros[2])   # 30 (tercero)
print(numeros[4])   # 50 (último)
print(numeros[5])   # ❌ IndexError: out of range

Índices negativos

En Python, los índices negativos cuentan desde el final:

numeros = [10, 20, 30, 40, 50]
print(numeros[-1])  # 50 (último)
print(numeros[-2])  # 40 (anteúltimo)
print(numeros[-5])  # 10 (primero)
Esquema visual
Lista:        [10,  20,  30,  40,  50]
Índice +:       0,   1,   2,   3,   4
Índice -:      -5,  -4,  -3,  -2,  -1

Longitud: len()

numeros = [10, 20, 30, 40, 50]
print(len(numeros))   # 5
print(len([]))        # 0

Para obtener el último elemento de una lista de longitud variable, lo más seguro es lista[-1] o lista[len(lista)-1].

Slicing (rebanadas)

Para obtener una sublista, usás lista[inicio:fin]. El fin no se incluye (igual que en range).

numeros = [10, 20, 30, 40, 50]
print(numeros[1:4])    # [20, 30, 40]
print(numeros[:3])     # [10, 20, 30] (desde el principio)
print(numeros[2:])     # [30, 40, 50] (hasta el final)
print(numeros[:])      # [10, 20, 30, 40, 50] (copia completa)
print(numeros[::2])    # [10, 30, 50] (cada 2)
print(numeros[::-1])   # [50, 40, 30, 20, 10] (al revés)

Mutabilidad: modificar una lista

nums = [10, 20, 30]
nums[1] = 99
print(nums)   # [10, 99, 30]

Métodos más usados

MétodoQué haceEjemplo
append(x)Agrega x al finallista.append(5)
insert(i, x)Inserta x en posición ilista.insert(0, 5)
remove(x)Borra la primera ocurrencia de xlista.remove(30)
pop(i)Saca y devuelve elemento en i (último por defecto)x = lista.pop()
sort()Ordena la lista (en el lugar)lista.sort()
sort(reverse=True)Ordena descendentelista.sort(reverse=True)
reverse()Invierte el ordenlista.reverse()
index(x)Devuelve la posición de xlista.index(30)
count(x)Cuenta cuántas veces aparece xlista.count(5)
copy()Devuelve una copia independienteotra = lista.copy()
Métodos vs funciones
• Métodos: se llaman con punto. lista.append(5). Modifican o consultan la lista.
• Funciones globales: reciben la lista como argumento. len(lista), sum(lista), max(lista).

Funciones útiles para listas

numeros = [3, 1, 4, 1, 5, 9, 2, 6]

len(numeros)   # 8
sum(numeros)   # 31 (suma)
max(numeros)   # 9
min(numeros)   # 1
sorted(numeros)  # [1, 1, 2, 3, 4, 5, 6, 9] devuelve nueva lista ordenada

Recorrer una lista

Dos formas típicas:

numeros = [10, 20, 30, 40]

# Por elemento (más común)
for n in numeros:
    print(n)

# Por índice (cuando necesitás la posición)
for i in range(len(numeros)):
    print(i, numeros[i])

# Por elemento e índice (con enumerate, lo mejor)
for i, n in enumerate(numeros):
    print(i, n)

Operadores útiles: in, +, *

5 in [1, 2, 3, 5]            # True (¿está 5?)
"casa" in ["auto", "casa"]   # True
3 not in [1, 2, 5]           # True

[1, 2] + [3, 4]     # [1, 2, 3, 4] (concatena)
[0] * 5             # [0, 0, 0, 0, 0] (repite)
[1, 2] * 3          # [1, 2, 1, 2, 1, 2]

Listas de listas (matrices)

Una lista puede contener otras listas. Sirve para representar matrices, tablas, etc.

matriz = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

print(matriz[0])      # [1, 2, 3] (primera fila)
print(matriz[0][2])   # 3 (fila 0, columna 2)

# Recorrer una matriz
for fila in matriz:
    for valor in fila:
        print(valor, end=" ")
    print()

Patrones típicos con listas

Sumar todos
numeros = [3, 1, 4, 1, 5, 9, 2, 6]
suma = 0
for n in numeros:
    suma = suma + n
print(suma)    # 31

# Más corto:
print(sum(numeros))
Contar cuántos cumplen una condición
numeros = [3, 1, 4, 1, 5, 9, 2, 6]
pares = 0
for n in numeros:
    if n % 2 == 0:
        pares = pares + 1
print(pares)   # 3 (4, 2, 6)
Filtrar (crear lista nueva con los que cumplen)
numeros = [3, 1, 4, 1, 5, 9, 2, 6]
mayores_a_3 = []
for n in numeros:
    if n > 3:
        mayores_a_3.append(n)
print(mayores_a_3)   # [4, 5, 9, 6]
Buscar máximo manualmente
numeros = [3, 1, 4, 1, 5, 9, 2, 6]
mayor = numeros[0]
for n in numeros:
    if n > mayor:
        mayor = n
print(mayor)    # 9

Tuplas: como listas pero inmutables

Una tupla es una colección ordenada como la lista, pero no se puede modificar una vez creada. Se escribe con paréntesis (o sin nada):

coord = (3, 4)
colores = ("rojo", "verde", "azul")
sin_parentesis = 1, 2, 3   # también es tupla

print(coord[0])      # 3
print(coord[1])      # 4
# coord[0] = 99      # ❌ TypeError: tuplas inmutables

¿Cuándo usar tupla en vez de lista?

  • Cuando los datos no deben cambiar (coordenadas, fechas, valores constantes).
  • Cuando devolvés varios valores desde una función.
  • Cuando querés "marcar" que algo es inmutable por seguridad.

Desempaquetado

Podés asignar varios valores a la vez:

x, y = (3, 4)
print(x)   # 3
print(y)   # 4

# También funciona con listas
nombre, edad = ["Bruno", 30]

# Truco para intercambiar variables
a = 1
b = 2
a, b = b, a    # ahora a=2, b=1

Comprensión de listas (list comprehension)

Forma compacta de crear una lista nueva a partir de otra secuencia, en una sola línea. Reemplaza el patrón "lista vacía + for + append".

# Forma larga
dobles = []
for x in [1, 2, 3, 4]:
    dobles.append(x * 2)
# dobles == [2, 4, 6, 8]

# Comprensión equivalente
dobles = [x * 2 for x in [1, 2, 3, 4]]
print(dobles)    # [2, 4, 6, 8]

Estructura: [expresión for elemento in secuencia]. La expresión se evalúa para cada elemento y el resultado va a la lista.

Con condición (filtrar)

Se agrega un if al final para quedarse solo con los elementos que cumplen la condición:

nums = [1, 2, 3, 4, 5, 6]
pares = [n for n in nums if n % 2 == 0]
print(pares)    # [2, 4, 6]

# Transformar y filtrar a la vez
cuadrados_pares = [n*n for n in nums if n % 2 == 0]
print(cuadrados_pares)    # [4, 16, 36]

Comprensión de diccionarios

Misma idea pero con {clave: valor for ...} para construir un diccionario:

cuadrados = {x: x**2 for x in range(4)}
print(cuadrados)    # {0: 0, 1: 1, 2: 4, 3: 9}

map() y filter()

Son dos funciones que le aplican otra función a todos los elementos de una lista, sin escribir el for. Entran en el segundo parcial, y ahí aparecen en todos los exámenes.

  • map(funcion, lista) transforma: le aplica la función a cada elemento y junta los resultados. Salen tantos elementos como entraron.
  • filter(funcion, lista) filtra: la función tiene que devolver True o False, y quedan sólo los elementos donde dio True, sin modificarlos.
def doble(n):
    return n * 2

def es_par(n):
    return n % 2 == 0

nums = [1, 2, 3, 4, 5]
print(list(map(doble, nums)))       # [2, 4, 6, 8, 10]
print(list(filter(es_par, nums)))   # [2, 4]
Tres detalles que hay que tener claros
• La función se pasa sin paréntesis: map(doble, nums), no map(doble(), nums).
• map y filter no devuelven una lista: hay que convertir el resultado con list(...). Un print(map(doble, nums)) muestra algo como <map object at 0x...>.
• Si se encadenan, el orden importa: list(filter(es_par, map(doble, nums))) primero duplica y después filtra → [2, 4, 6, 8, 10]. Al revés, list(map(doble, filter(es_par, nums))) primero filtra y después duplica → [4, 8].

También sirven las funciones que ya trae Python: list(map(len, ["ana", "LUIS", "Marta"])) da [3, 4, 5].

Errores típicos en listas
• Acceder a índice fuera de rango: lista[10] en lista de 5 elementos.
• Modificar lista mientras la recorrés: resultados imprevisibles. Si necesitás filtrar, creá lista nueva.
• Confundir append con +: lista.append([1,2]) agrega la lista entera como un solo elemento. lista + [1,2] concatena.
• No darse cuenta que sort() modifica la lista y devuelve None: x = lista.sort() ❌. Lo correcto: lista.sort() y después usar lista.
↑ Volver al índice
Segundo parcial Unidades 4 (diccionarios) a 6
5 Diccionarios

¿Qué es un diccionario?

Un diccionario es una colección de pares clave:valor. A diferencia de una lista (donde accedés por posición numérica), en un diccionario accedés por una clave que vos elegís: puede ser un texto, un número o cualquier valor inmutable.

persona = {"nombre": "Bruno", "edad": 30, "ciudad": "Buenos Aires"}

print(persona["nombre"])   # "Bruno"
print(persona["edad"])     # 30

Cuando vendría bien un diccionario

Cuando los datos tienen "etiquetas naturales": en vez de recordar que la posición 0 es el nombre y la 1 la edad, escribís persona["nombre"] y se entiende solo.

ListaDiccionario
persona = ["Bruno", 30, "BA"]persona = {"nombre":"Bruno", "edad":30, "ciudad":"BA"}
Accedés por posición: persona[0]Accedés por clave: persona["nombre"]
Hay que recordar el ordenLas claves explican qué es cada cosa

Sintaxis

  • Llaves { } (no corchetes).
  • Cada par tiene la forma clave: valor.
  • Los pares se separan con comas.
  • Las claves suelen ser strings o números enteros. Los valores pueden ser cualquier cosa (incluso otra lista o diccionario).

Crear, agregar, modificar, borrar

# Vacío
persona = {}

# Agregar (clave nueva)
persona["nombre"] = "Bruno"
persona["edad"] = 30

# Modificar (clave existente - misma sintaxis que agregar)
persona["edad"] = 31

# Borrar
del persona["edad"]
# o también
edad = persona.pop("edad")    # saca y devuelve el valor

print(persona)   # {'nombre': 'Bruno'}

¿Existe una clave?

Antes de acceder a una clave que podría no existir, conviene verificar:

if "nombre" in persona:
    print("Tiene nombre:", persona["nombre"])

# Para verificar que NO esté
if "telefono" not in persona:
    print("No tiene teléfono")
KeyError: la clave no existe
Si accedés con persona["clave_que_no_existe"], Python tira KeyError.

Soluciones:
• Usá in antes de acceder.
• O usá persona.get("clave"): devuelve None si no existe en lugar de tirar error.
• persona.get("clave", "default"): devuelve "default" si no existe.

Métodos útiles

MétodoDevuelveEjemplo
d.keys()Todas las clavespersona.keys() → dict_keys(['nombre', 'edad'])
d.values()Todos los valorespersona.values() → dict_values(['Bruno', 30])
d.items()Pares (clave, valor)persona.items()
d.get(k)Valor o None si no existepersona.get("foo") → None
d.get(k, default)Valor o default si no existepersona.get("foo", 0) → 0
d.update(otro)Agrega los pares de otro dictpersona.update({"tel": "1234"})
len(d)Cantidad de pareslen(persona) → 2

Recorrer un diccionario

persona = {"nombre": "Bruno", "edad": 30, "ciudad": "BA"}

# Por clave (lo más común)
for clave in persona:
    print(clave, "→", persona[clave])

# Por valores
for valor in persona.values():
    print(valor)

# Por pares clave-valor (lo más útil)
for clave, valor in persona.items():
    print(f"{clave}: {valor}")

Listas de diccionarios

Estructura muy común: cada elemento de una lista es un diccionario. Es la forma natural de representar "una tabla con filas".

personas = [
    {"nombre": "Ana",   "edad": 25, "ciudad": "BA"},
    {"nombre": "Bruno", "edad": 30, "ciudad": "Rosario"},
    {"nombre": "Carla", "edad": 28, "ciudad": "BA"}
]

# Recorrer
for p in personas:
    print(p["nombre"], "tiene", p["edad"], "años")

# Filtrar mayores de 27
mayores = []
for p in personas:
    if p["edad"] > 27:
        mayores.append(p)
print(mayores)

# Promedio de edad
suma = 0
for p in personas:
    suma = suma + p["edad"]
promedio = suma / len(personas)
print("Promedio:", promedio)

Patrones típicos con diccionarios

Patrón "contar frecuencias"
letras = "missisipi"
conteo = {}
for letra in letras:
    if letra in conteo:
        conteo[letra] = conteo[letra] + 1
    else:
        conteo[letra] = 1
print(conteo)   # {'m': 1, 'i': 4, 's': 3, 'p': 1}
Patrón "agrupar"
personas = [
    {"nombre": "Ana", "ciudad": "BA"},
    {"nombre": "Bruno", "ciudad": "Rosario"},
    {"nombre": "Carla", "ciudad": "BA"}
]

por_ciudad = {}
for p in personas:
    c = p["ciudad"]
    if c not in por_ciudad:
        por_ciudad[c] = []
    por_ciudad[c].append(p["nombre"])
print(por_ciudad)
# {'BA': ['Ana', 'Carla'], 'Rosario': ['Bruno']}

Validación de usuarios (clásico de parcial)

users = {"bruno": "clave123", "juan": "pwd456"}

def ingreso(usr_dict):
    u = input("Usuario: ")
    cl = input("Clave: ")
    if u in usr_dict:
        if usr_dict[u] == cl:
            return True
    return False

while not ingreso(users):
    print("Datos erróneos, volvé a intentar")
print("¡Bienvenido!")

Diccionarios anidados

Un diccionario puede tener como valor otro diccionario:

datos = {
    "bruno": {"edad": 30, "ciudad": "BA"},
    "juan":  {"edad": 25, "ciudad": "Rosario"}
}

print(datos["bruno"]["edad"])     # 30
print(datos["juan"]["ciudad"])    # Rosario
Errores típicos con diccionarios
• KeyError por acceder a clave que no existe (usá get o in).
• Confundir corchetes con llaves: lista [ ], diccionario { }.
• Usar listas como claves (no se puede, son mutables).
• Olvidar inicializar un diccionario antes de empezar a llenarlo.
↑ Volver al índice
6 Archivos y manejo de errores

¿Por qué trabajar con archivos?

Cuando un programa termina, se pierden todas las variables. Para persistir datos (que sobrevivan más allá de la ejecución), tenés que escribirlos en un archivo en disco. Después podés leer esos datos en otra ejecución.

Casos típicos:

  • Guardar el resultado de un cálculo.
  • Cargar una lista de usuarios o productos.
  • Procesar datasets (CSV).
  • Generar reportes en texto.

Abrir un archivo: open()

archivo = open("datos.txt", "r")
# ... operaciones ...
archivo.close()

Toma dos parámetros: el nombre (con ruta si está en otra carpeta) y el modo.

ModoSignificaDetalles
"r"Read (lectura)Falla si no existe.
"w"Write (escritura)Crea el archivo si no existe. Sobrescribe si existe (cuidado).
"a"Append (agregar al final)Crea si no existe. Conserva el contenido previo.
"r+"Lectura + escrituraFalla si no existe.
¡Cuidado con "w"!
Abre el archivo y borra todo su contenido antes de escribir. Si querés agregar sin perder lo anterior, usá "a".

Leer un archivo

# Opción 1: leer todo como un solo string
archivo = open("datos.txt", "r")
contenido = archivo.read()
print(contenido)
archivo.close()

# Opción 2: leer línea por línea (recomendado para archivos grandes)
archivo = open("datos.txt", "r")
for linea in archivo:
    print(linea.strip())   # strip() quita el salto de línea final
archivo.close()

# Opción 3: leer todas las líneas a una lista
archivo = open("datos.txt", "r")
lineas = archivo.readlines()
archivo.close()
print(lineas)   # ['linea 1\n', 'linea 2\n', ...]

Escribir en un archivo

archivo = open("salida.txt", "w")
archivo.write("Hola\n")
archivo.write("Segunda línea\n")
archivo.close()
Salto de línea: \n
Si querés escribir en varias líneas, tenés que agregar \n al final de cada texto. write() NO lo hace solo, a diferencia de print().

La forma recomendada: with

Abre el archivo y lo cierra automáticamente al terminar el bloque, incluso si hay error. Es lo que se usa en código profesional.

with open("datos.txt", "r") as archivo:
    for linea in archivo:
        print(linea.strip())
# Acá ya está cerrado automáticamente

Lo podés usar también para escritura:

with open("salida.txt", "w") as f:
    f.write("Línea 1\n")
    f.write("Línea 2\n")

Procesar líneas: strip() y split()

  • linea.strip(): quita espacios y saltos de línea al principio y final.
  • linea.split(","): divide la línea por comas y devuelve una lista.
  • linea.split() sin argumento: divide por espacios.
Leer un CSV simple manualmente
with open("notas.csv", "r") as f:
    for linea in f:
        partes = linea.strip().split(",")
        nombre = partes[0]
        nota = int(partes[1])
        print(f"{nombre}: {nota}")

Acumular datos en una estructura

notas = []
with open("notas.txt", "r") as f:
    for linea in f:
        notas.append(int(linea.strip()))

print("Promedio:", sum(notas) / len(notas))
print("Máximo:", max(notas))

Manejo de errores

Un error (o excepción) ocurre cuando algo sale mal: un archivo no existe, el usuario ingresa texto donde esperabas número, dividís por cero. Por defecto, cuando ocurre un error, el programa se corta.

Para que el programa pueda recuperarse, usás try/except.

try / except

try:
    n = int(input("Ingresá un número: "))
    print(n * 2)
except ValueError:
    print("Eso no fue un número")
  • try: "intentá ejecutar este código".
  • except: "si surge un error de tipo X, hacé esto otro".

Si el código del try se ejecuta sin errores, el except se saltea. Si hay error, se ejecuta el except correspondiente.

Excepciones más comunes

ExcepciónCuándo ocurre
ValueErrorValor no convertible (el tipo sí es correcto): int("hola"), float("abc")
ZeroDivisionErrorDivisión por cero: 5 / 0
FileNotFoundErrorAbrir archivo inexistente con "r"
KeyErrorAcceder a clave no existente en diccionario
IndexErrorAcceder a índice fuera de rango en lista
TypeErrorTipos incompatibles: "a" + 5
NameErrorUsar variable no definida

Múltiples except

Podés manejar errores distintos por separado:

try:
    archivo = open("datos.txt", "r")
    n = int(archivo.readline())
    resultado = 10 / n
    print(resultado)
except FileNotFoundError:
    print("No existe el archivo")
except ValueError:
    print("El archivo no tiene un número válido")
except ZeroDivisionError:
    print("No se puede dividir por cero")

Capturar cualquier excepción

try:
    # algo que puede fallar
    pass
except Exception as e:
    print("Falló algo:", e)

Con as e guardás el objeto excepción en e y podés imprimirlo o usarlo.

else y finally

  • else: se ejecuta solo si NO hubo excepción.
  • finally: se ejecuta siempre (haya error o no). Útil para "limpiar" recursos.
try:
    archivo = open("datos.txt", "r")
    contenido = archivo.read()
except FileNotFoundError:
    print("No existe el archivo")
else:
    print("Lectura exitosa")
    print(contenido)
finally:
    print("Termina la operación")

Validación robusta de input (clásico de parcial)

def pedir_entero_positivo(cartel):
    while True:
        try:
            n = int(input(cartel))
            if n > 0:
                return n
            else:
                print("Tiene que ser mayor que 0")
        except ValueError:
            print("Tiene que ser un entero")

num = pedir_entero_positivo("Ingresá un natural: ")
print("Recibido:", num)

Este patrón cubre dos situaciones a la vez: que el usuario escriba algo no numérico y que escriba un número inválido (≤ 0).

↑ Volver al índice
7 Pandas (análisis de datos)

¿Qué es una biblioteca?

Una biblioteca (library) es código que otros escribieron y podés usar en tus programas importándolo. Evita "reinventar la rueda". Python viene con muchas bibliotecas incluidas (estándar) y miles más se pueden instalar.

import pandas as pd
import matplotlib.pyplot as plt
  • import: carga la biblioteca.
  • as: le da un nombre más corto (alias) para usarla.

pd es el alias estándar de Pandas. plt es el de Matplotlib. Esos alias son convención universal: usalos así.

¿Qué es Pandas?

Pandas es la biblioteca estándar para trabajar con datos en forma tabular (filas y columnas, como una planilla Excel) en Python. Se usa muchísimo en ingeniería, ciencia de datos, finanzas y análisis en general.

Estructuras principales

  • DataFrame: una tabla con filas y columnas (con etiquetas).
  • Series: una sola columna (o fila) con etiquetas.

Crear un DataFrame

Desde un diccionario

import pandas as pd

datos = {
    "nombre": ["Ana", "Bruno", "Carla", "Diego"],
    "edad":   [25, 30, 28, 35],
    "ciudad": ["CABA", "Rosario", "CABA", "Mendoza"]
}
df = pd.DataFrame(datos)
print(df)

Genera una tabla:

   nombre  edad   ciudad
0     Ana    25     CABA
1   Bruno    30  Rosario
2   Carla    28     CABA
3   Diego    35  Mendoza

Desde un archivo CSV

CSV (Comma-Separated Values) es el formato más común para datos tabulares: un archivo de texto donde cada fila es una línea y las columnas se separan por comas.

df = pd.read_csv("datos.csv")

Si el separador es punto y coma (común en archivos europeos):

df = pd.read_csv("datos.csv", sep=";")

Explorar un DataFrame

ComandoQué muestra
df.head()Primeras 5 filas (o las que pidas: df.head(10))
df.tail()Últimas 5 filas
df.shapeTupla (filas, columnas)
df.columnsNombres de columnas
df.dtypesTipo de dato de cada columna
df.info()Resumen: tipos, nulos, memoria
df.describe()Estadísticas básicas (promedio, min, max, etc.) de columnas numéricas

Acceder a columnas

df["edad"]              # la columna edad como Series
df[["nombre", "edad"]]  # varias columnas (corchete doble) → DataFrame nuevo
Corchete simple vs doble
• df["edad"] con corchetes simples: devuelve una Series (la columna).
• df[["edad"]] con corchetes dobles: devuelve un DataFrame con esa única columna.
• Para varias columnas, sí o sí dobles: df[["a", "b"]].

Acceder a filas: .iloc y .loc

  • df.iloc[i]: por posición (índice numérico).
  • df.loc[i]: por etiqueta del índice (suele coincidir cuando el índice es 0,1,2,...).
df.iloc[0]      # primera fila
df.iloc[-1]     # última fila
df.iloc[0:3]    # primeras 3 filas (slicing)

df.loc[0, "nombre"]   # valor de fila 0, columna nombre

Filtrar filas (lo más usado)

Le pasás al DataFrame una condición y te devuelve solo las filas que la cumplen:

# Personas mayores de 27
df[df["edad"] > 27]

# Personas de CABA
df[df["ciudad"] == "CABA"]

# Combinado: mayor de 25 Y de CABA
df[(df["edad"] > 25) & (df["ciudad"] == "CABA")]

# O: de CABA o de Mendoza
df[(df["ciudad"] == "CABA") | (df["ciudad"] == "Mendoza")]

# Más elegante con isin:
df[df["ciudad"].isin(["CABA", "Mendoza"])]
En pandas se usa &, |, ~ (NO and, or, not)
Con DataFrames las condiciones se combinan con:
• & en lugar de and
• | en lugar de or
• ~ en lugar de not

Y siempre envolvé cada condición con paréntesis: (df["a"] > 5) & (df["b"] == "x").

Operaciones agregadas (estadísticas)

df["edad"].mean()       # promedio
df["edad"].max()        # máximo
df["edad"].min()        # mínimo
df["edad"].sum()        # suma total
df["edad"].count()      # cantidad de no-nulos
df["edad"].std()        # desvío estándar
df["edad"].median()     # mediana

Conteos y agrupamientos

# Cuántos hay de cada valor
df["ciudad"].value_counts()
# CABA       2
# Rosario    1
# Mendoza    1

# Agrupar y agregar
df.groupby("ciudad")["edad"].mean()
# Promedio de edad por ciudad

df.groupby("ciudad").size()
# Cantidad de filas por ciudad

Ordenamiento

df.sort_values("edad")                  # ascendente
df.sort_values("edad", ascending=False) # descendente
df.sort_values(["ciudad", "edad"])      # primero por ciudad, después por edad

Agregar / modificar columnas

df["mayor_de_edad"] = df["edad"] >= 18
df["edad_doble"] = df["edad"] * 2
df["categoria"] = "joven"   # mismo valor en toda la columna

apply: aplicar una función a cada fila o columna

def categoria(edad):
    if edad < 18:
        return "menor"
    elif edad < 65:
        return "adulto"
    else:
        return "jubilado"

df["cat"] = df["edad"].apply(categoria)

Borrar columnas o filas

df = df.drop("ciudad", axis=1)        # borra columna
df = df.drop(0, axis=0)               # borra fila con índice 0

Valores nulos

df.isnull()           # DataFrame de True/False
df.isnull().sum()     # cuántos nulos por columna
df.dropna()           # borra filas con cualquier nulo
df.fillna(0)          # rellena nulos con 0
Errores típicos en Pandas
• Confundir corchete simple y doble al pedir columnas.
• Usar and/or en lugar de &/| para filtros.
• Olvidar paréntesis en condiciones combinadas.
• Modificar un slice creyendo que afecta al original (puede no funcionar; usá .copy() si querés trabajar aparte).
↑ Volver al índice
8 Matplotlib (gráficos)

¿Qué es Matplotlib?

Matplotlib es la biblioteca estándar para crear gráficos en Python. Permite hacer gráficos de línea, barras, dispersión, histogramas, tortas, y mucho más. La parte que más se usa es pyplot:

import matplotlib.pyplot as plt

plt es el alias convencional.

Gráfico de línea básico

x = [1, 2, 3, 4, 5]
y = [2, 4, 1, 5, 3]

plt.plot(x, y)
plt.show()
  • plt.plot(x, y): arma el gráfico (puntos x,y unidos con línea).
  • plt.show(): lo muestra. En Colab no siempre hace falta: suele aparecer solo.

Agregar títulos y etiquetas

plt.plot(x, y)
plt.title("Mi primer gráfico")
plt.xlabel("Tiempo (s)")
plt.ylabel("Velocidad (m/s)")
plt.show()

Tipos de gráficos principales

TipoFunciónCuándo usar
Líneaplt.plot(x, y)Evolución en el tiempo, funciones continuas
Barras verticalesplt.bar(x, y)Comparar categorías
Barras horizontalesplt.barh(x, y)Igual pero con etiquetas largas
Dispersiónplt.scatter(x, y)Correlación entre dos variables
Histogramaplt.hist(datos, bins=10)Distribución de una variable numérica
Tortaplt.pie(valores, labels=etiq)Proporciones de un total (pocas categorías)
Cajaplt.boxplot(datos)Mostrar dispersión y outliers

Ejemplo: gráfico de barras

meses = ["Ene", "Feb", "Mar", "Abr"]
ventas = [120, 90, 150, 180]

plt.bar(meses, ventas)
plt.title("Ventas por mes")
plt.xlabel("Mes")
plt.ylabel("Ventas")
plt.show()

Ejemplo: dispersión

edades = [25, 30, 35, 28, 45, 50]
salarios = [40000, 50000, 65000, 45000, 80000, 90000]

plt.scatter(edades, salarios)
plt.xlabel("Edad")
plt.ylabel("Salario")
plt.title("Relación edad-salario")
plt.show()

Ejemplo: histograma

edades = [22, 25, 24, 30, 28, 35, 40, 26, 33, 29, 31, 27, 32]

plt.hist(edades, bins=5)
plt.xlabel("Edad")
plt.ylabel("Frecuencia")
plt.title("Distribución de edades")
plt.show()

El parámetro bins indica en cuántos rangos dividir.

Personalización de líneas

plt.plot(x, y,
         color="red",      # color de la línea
         linestyle="--",   # estilo: '-', '--', ':', '-.'
         linewidth=2,      # grosor
         marker="o",       # marca cada punto: 'o', 's', '^', 'x'
         markersize=8)     # tamaño del marker

Múltiples series en un mismo gráfico

x = [1, 2, 3, 4, 5]
y1 = [2, 4, 6, 8, 10]
y2 = [1, 4, 9, 16, 25]

plt.plot(x, y1, label="Producto A")
plt.plot(x, y2, label="Producto B")
plt.legend()       # muestra las etiquetas
plt.grid(True)     # cuadrícula
plt.show()

Conectar Pandas con Matplotlib

Podés graficar directamente desde un DataFrame:

import pandas as pd
import matplotlib.pyplot as plt

df = pd.read_csv("ventas.csv")

# Forma 1: pasar columnas a plt
plt.plot(df["mes"], df["total"])
plt.title("Ventas mensuales")
plt.show()

# Forma 2: usar .plot() del DataFrame (más compacto)
df.plot(x="mes", y="total", kind="bar")
plt.show()

El parámetro kind de df.plot() puede ser: 'line', 'bar', 'barh', 'hist', 'scatter', 'pie', 'box'.

Subplots: varios gráficos en una figura

fig, ax = plt.subplots(1, 2, figsize=(10, 4))   # 1 fila, 2 columnas

ax[0].plot(x, y1)
ax[0].set_title("Serie 1")

ax[1].bar(meses, ventas)
ax[1].set_title("Ventas")

plt.show()

Guardar el gráfico

plt.plot(x, y)
plt.savefig("grafico.png")    # antes de show()
plt.show()
Errores típicos en Matplotlib
• Olvidar plt.show() al final (a veces no aparece nada).
• Mezclar gráficos sin plt.figure() nuevo: te superponen.
• Pasar listas de distinto largo en x e y: plt.plot tira ValueError. En x podés poner números o textos (por ejemplo los meses), pero tiene que haber un valor de y por cada uno.
• Olvidar etiquetas y título: el gráfico queda incompleto.
↑ Volver al índice