No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

No se trata de lo que quieres comprar, sino de quién quieres ser. Invierte en tu educación con el precio especial

Antes: $249

Currency
$209

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Suscríbete

Termina en:

12 Días
15 Hrs
15 Min
17 Seg

Muestreo estratificado en Python

6/22
Recursos

Aportes 39

Preguntas 14

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Muestreo Estratificado en Python

Yo lo entendí de esta forma:

  1. Separa los datos por categorías (valores estratificados).
  2. Define las categorías que quieres en tú muestro y su proporción.
  3. Toma tantos datos como necesites de cada categoría para llegar a la proporción deseada.
  4. Junta esas muestras de cada categoría para tu muestreo final.

Explicación del ejemplo

Se crean dichas categorías a partir de la delegación y el tipo, esta información se almacena en la columna estratificado:

econdata['estratificado'] = econdata['delegacion'] + "," + econdata['tipo']
(econdata['estratificado'].value_counts() / len(econdata)).sort_values(ascending=False)

Con esto ya tenemos los datos por categorías (paso 1) y podemos ver su proporción real:

Para nuestro muestreo definimos las siguientes proporciones (paso 2):

  • Cuautémoc, Hotel: 0.5,
  • Cuautémoc, Museo: 0.2,
  • Venustiano Carranza, Hotel: 0.1,
  • Cuauhtémoc, Mercado: 0.1,
  • Venustiano Carranza, Mercado: 0.1

Para crear dicha proporción a partir de los datos originales se utiliza la siguiente función que encuentra el número de muestras necesario de cada categoría (paso 3), hace un sampleo simple dentro de dicha categoria y luego junta esas muestras (paso 4):

def data_estratificada(econdata, nombres_columnas_estrat, valores_estrat, prop_estrat, random_state=None):

  df_estrat = pd.DataFrame(columns = econdata.columns) 

  pos = -1
  for i in range(len(valores_estrat)):
    pos += 1
    if pos == len(valores_estrat) - 1: 
      ratio_len = len(econdata) - len(df_estrat)
    else:
      ratio_len = int(len(econdata) * prop_estrat[i])

    df_filtrado = econdata[econdata[nombres_columnas_estrat] ==valores_estrat[i]]
    df_temp = df_filtrado.sample(replace=True, n=ratio_len, random_state=random_state)

    df_estrat = pd.concat([df_estrat, df_temp]) 
  return df_estrat

Utiliza este código para crear el sampleo:

valores_estrat = ['Cuautémoc,Hotel', 'Cuautémoc,Museo', 'Venustiano Carranza,Hotel', 'Cuauhtémoc,Mercado','Venustiano Carranza,Mercado']
prop_estrat = [0.5, 0.2, 0.1, 0.1, 0.1]
df_estrat = data_estratificada(econdata, 'estratificado', valores_estrat, prop_estrat, random_state=42)
df_estrat

Adicionalmente, puedes usar este código para ver la proporción final de tus datos:

(df_estrat['estratificado'].value_counts()/len(df_estrat)).sort_values(ascending=False)

Si todo salió bien, deberías ver algo similar a esto:

Con esto ya tienes una muestra en las proporciones que deseábamos en un principio.

Para entender este muestreo vamos a analizar que sucede cuando apliquemos un muestreo aleatorio simple vs un estratificado a los registros de Mercados que se encuentran en la delegacion Venustiano Carranza al cual me referire como el grupo “MVC” . Escogi el grupo MVS dado que de los 230 registros que tiene nuestro dataset (poblacion) solo el 4.7% (11 registros)son mercados en en la delegacion venustiano carranza, por lo cual es muy sensible a que estos registros desaparezcan al hacer un muestreo aleatorio. en cambio al hacer un estratificado podemos asignar una fraccion a recolectar de cada grupo y asi lograr que el grupo MVC no desaparesca ya que si queremos hacer un muestreo de 40 registros (n = 40) el 4.78% de las muestras seran del grupo MVC osea 1.8 registros que redondeando serian 2. en resumen al hacer un muestro n =40 la probabilidad de que se seleccione un registro del grupo MVC usando un muestreo aleatorio simple es muy bajo siendo probable que no se recoja ningun registro MVC al aplicar el muestreo, pero si en cambio usamos un muestreo estratificado recogeremos al menos 2 registros del grupo.
pd: sin ayuda de la comunidad no hubiera entendido la clase, gracias !

No había entendido bien el muestreo estratificado, pero al hacer el código ya lo entendí mejor.

  • Básicamente es muy útil cuando quieres indicar qué proporción de datos de una misma categoría quieres obtener.
  • Obtener el mismo muestreo (con las mismas condiciones) gracias al random_state.

Creo que esta es una alternativa mas clara y menos larga:

data['strat'] = data['delegacion'] + " - " + data['tipo']

def stratified_sample(data, category, size):
  strat_values = data[category].unique()
  strat_props = (data[category].value_counts() / len(data))

  strat_sample = pd.DataFrame(columns = data.columns)

  for value in strat_values:
    strat_sample = pd.concat([strat_sample, data[(data[category] == value)].sample(n = round(strat_props[value]*size)) ])
  
  return strat_sample

strat_sample = stratified_sample(data, 'strat', 40)

No me está quedando del todo claro que papel juega el random_state 😕

Me parece que se le complico mucho a la profe el explicar este tipo de muestreo, te lo explico de forma sencilla:

Por ejemplo, si tiene una población de 50 000 personas en una ciudad y desea encuestarlas, probablemente no pueda encuestarlas a todas. Podría encuestar a 100 y extrapolar los resultados. Pero querrá asegurarse de que el grupo de muestra (esas 100 personas que encuesta) realmente represente a la población de la ciudad en su conjunto. Entonces, si el 20 % de la ciudad son asiáticos, querrás asegurarte de que el 20 % del grupo de muestra (20 personas) también sean asiáticos.

Esto, en esencia, es un muestreo estratificado: garantizar que cada subgrupo (o ‘estrato’) en su muestra esté representado en la porción correcta de toda la población.

pd: el codigo de la profe NO devuelve dicha muestra, pueden verificar esto en el colab al ver que econdata tiene 230 registros y df_estrat tambien tiene 230 registros

Muy mal explicado el código

Otro curso que se lleva todos los aplausos.

​Aquí te doy un ejemplo de cómo realizar el muestreo estratificado en Python con la librería pandas:

Copiar código
import pandas as pd

Crear un dataframe

data = {'Género': ['Hombre', 'Mujer', 'Hombre', 'Mujer', 'Hombre', 'Mujer'],
        'Edad': [22, 38, 27, 35, 18, 45],
        'Ingresos': [50000, 100000, 75000, 120000, 90000, 80000]}
df = pd.DataFrame(data)

Crear estratos

strat_df = df.groupby(
strat_df =
'Género').apply(lambda x: x.sample(frac=0.3))

Muestra estratificada

print(strat_df)
  • En este ejemplo, se crea un marco de datos con tres columnas: Género, Edad e Ingresos. Luego, se agrupa el dataframe por la columna “Género” y se aplica una función de prueba de forma aleatoria a cada estrato con una fracción de 0.3. El resultado es una muestra estratificada donde el 30% de los elementos de cada estrato son seleccionados al azar.

La librería numpy también tiene la función ‘random.choice’ que permite elegir elementos al azar de una lista o una matriz de una manera similar.

Me pareció un poco complicado el código de la profesora, por lo que me dí la tarea de escribir mi propio código:

def stratified_sampling(df, col_name, size, random_state=0):
    ratio_df = df[col_name].value_counts() / len(df) 
    
    strat_idx = []
    for val in ratio_df.index:
        n_val = int(ratio_df[val] * len(df)) 
        size_per_val = round(n_val * size)
        strat = df[df[col_name]==val].sample(size_per_val, random_state=random_state)
        strat_idx.append(strat.index)
 
    strat_idx = [i for sublist in strat_idx for i in sublist]

    return df.iloc[strat_idx]

Hola, si quedaste como, que, que rayos?
que signfica esto?
bueno, tranquil@, yo tambien sentí lo mismo y tuve que tomarme mi tiempo para digerirlo.
Cosas que debes de tener en cuenta.

  1. Es una técnica: Esto significa que pueden haber otras formas de extraer informacion y evaluarlas.
    posiblemente esta es la mas popular.
    La cual busca que cada subgrupo(estrato, categoria) pueda representar la poblacion.
    ahora, lo que se busca es tener una vision amplia de cual es la distribucion real de los datos(sacando solo unos valores especificos) para poder concluir su distribucion.
  2. y luego, como resultado tener la muestra final, en esta muestra final, lo que se busca entonces es que allí esten representados los datos o subgrupos segun su proporcion.

Le hice unos pequeños cambio al código, nos permite colocar el tamaño de la muestra.

def mi_estratificado (datos,columna,size,valores_estrat ,random_state = None):
  df_estrat = pd.DataFrame(columns=datos.columns)
  datos_en_col = datos[columna].unique()
  con = 0
  for i in datos_en_col :
    df_filtrado = datos[datos[columna] == datos_en_col[con]]
    df_temp = df_filtrado.sample(replace=True , n= int(valores_estrat[con] *size) ,random_state= random_state)
    df_estrat = pd.concat([df_estrat,df_temp])
    con += 1
  return df_estrat
### Para Probarlo
val_estrat = [0.5,0.2,0.1,0.1,0.1]
df_p = mi_estratificado(econodata,'estratificado',150,val_estrat, random_state=4)
print((df_p['estratificado'].value_counts()/len(df_p)).sort_values(ascending=False))
df_p

Explicación de la función data_estratificada

Le agreugue el parametro tamaño de muestra para hacer mas entendible la función

Definimos la función con sus variables

def data_estratificad(econdata,nombres_columnas_estrat,
                      valores_estrat, prop_estrat, 
                      tamano_muestra,random_state=None):
    '''Función que dado un dataFrame toma una muestra estratificada
    
    Argumentos:
    econdata {DataFrame}    -- DataFrame del cual tomaremos la muestra
    nombres_columnas {list} -- Valores a partir de los cuales se va a estratificar el DataFrame
    valores_estrat {list}   -- Valores del porcentaje de la muestra que tomara cada nombre de la lista anterior
    tamano_muestra {int}    -- Cantidad de datos que tendra la muestra
    random_state {int}      -- Función que nos permite elegir la semilla de los números pseudo-aleatorios
    '''
    
    'Creamos un DataFrame vacio con las mismas columnas donde guardaremos los datos'
    df_estrat = pd.DataFrame(columns= econdata.columns)
    
    'Contador auxiliar para ir pasando la lista'
    pos = -1
    
    'Ciclo for el cual va cambiando los valores donde seleccionamos la cantidad de datos por cada nombre'
    'Función range(len(valores_estrat)) nos indica que iremos desde 0 hasta la cantidad de entradas que tenga la lista valores_estrat'
    'esto para recorrer toda la lista'
    for i in range(len(valores_estrat)):
        
        'sumamos 1 a pos'
        pos +=1
        
        'Ciclo if el cual nos ayudara a saber la cantidad de datos que vamos a extraer de cada clasificador'
        'si posicion es igual a ultima:'
        if pos == len(valores_estrat)-1:
            'la cantidad de valores que obtendremos sera el tamaño de la muestra menos los que ya tenemos'
            ratio_len = tamano_muestra - len(df_estrat)
            'En caso de no sea la ultima posición'
            
        else:
            'la cantidad de valores que tendremos para este clasificador se obtendra de la siguente forma'
            'multiplicamos el tamaño de la muestra por la proporcion que corresponde a ese clasificador'
            'como el valor puede no ser entero, lo convertimos en entero'
            ratio_len = int(tamano_muestra*prop_estrat[i])
        
        'en el DataFrame df_filtrado filtramos los valores de la columna que incluyan al clasificador'
        df_filtrado = econdata[econdata[nombres_columnas_estrat]==valores_estrat[i]]
        
        'obtenemos una muestra del tamano obtenido en ratio_len y la agregamos al dataFrame df_temp'
        df_temp = df_filtrado.sample(replace=True, n=ratio_len, random_state=random_state)
        
        'Concatenamos la información al DataFrame df_estrat, de tal forma que se guardan los valores de todos los clasificadores'
        df_estrat = pd.concat([df_estrat,df_temp])
    return df_estrat
ValueError Traceback (most recent call last) [\<ipython-input-16-abac41bc8492>](https://localhost:8080/#) in \<cell line: 3>() 1 valores\_estrat = \['Cuautémoc,Hotel', 'Cuautémoc,Museo', 'Venustianos Carranza,Hotel', 'Cuauhtémoc,Mercado', 'Venustiano Carranza,Mercado'] 2 prop\_estrat = \[0.5, 0.2, 0.1, 0.1, 0.1] \----> 3 df\_estrat = data\_estratificada(econdata, 'estratificado', valores\_estrat, prop\_estrat, random\_state = 42) 4 df\_estrat 2 frames[/usr/local/lib/python3.10/dist-packages/pandas/core/sample.py](https://localhost:8080/#) in sample(obj\_len, size, replace, weights, random\_state) 148 raise ValueError("Invalid weights: weights sum to zero") 149 \--> 150 return random\_state.choice(obj\_len, size=size, replace=replace, p=weights).astype( 151 np.intp, copy=False 152 ) mtrand.pyx in numpy.random.mtrand.RandomState.choice() ValueError: a must be greater than 0 unless no samples are taken

Bueno, me costo mas de lo que me hubiera gustado la verda, pero aca les dejo el reto que hice con una dataset de dibujitos que encontre en kaggle (voy a hacer el muestreo estratificado, ya que los otros son simples dentro de todo :p)


# Creamos una variable nueva en el dataset
df_cartoons['estratificado'] = df_cartoons['Country']+','+df_cartoons['Original Channel']
(df_cartoons['estratificado'].value_counts() / len(df_cartoons)).sort_values(ascending=False)

def data_estratificada(df_cartoons, nombres_columnas_estrat, valores_estrat, prop_estrat, random_state=None):
    
    df_estrat = pd.DataFrame(columns = df_cartoons.columns) # Creamos un data frame vacío con los nombres de las columnas de df_cartoons

    pos = -1
    for i in range(len(valores_estrat)): # iteración sobre los valores estratificados
        pos += 1
        if pos == len(valores_estrat) - 1: 
            ratio_len = len(df_cartoons) - len(df_estrat) # si es la iteración final calcula el número de valores de salida tenga el mismo número de filas que de entrada
        else:
            ratio_len = int(len(df_cartoons) * prop_estrat[i]) # calcula el número de filas según la proporción deseada

        df_filtrado = df_cartoons[df_cartoons[nombres_columnas_estrat] ==valores_estrat[i]] # filtra los datos de origen según los valores seleccionados en la estratificación de datos
        df_temp = df_filtrado.sample(replace=True, n=ratio_len, random_state=random_state) # haz un sample de los datos filtrados usando la ratio que hemos calculado
        
        df_estrat = pd.concat([df_estrat, df_temp]) # junta las tablas de sample con la estratificada para producir el resultado final
        
    return df_estrat # Return the stratified, re-sampled data  

valores_estrat = ['United States,Netflix', 'United States,Cartoon Network', 'United States,Adult Swim']
prop_estrat = [0.6, 0.3, 0.1]
df_estrat = data_estratificada(df_cartoons, 'estratificado', valores_estrat, prop_estrat, random_state=42)
df_estrat

(df_estrat['estratificado'].value_counts()/len(df_estrat)).sort_values(ascending=False)

Creo que se hubiera aprendido más si se daba un ejemplo más básico.

No entendí nada 😕

¡Hola muchach@s!

Al tomar una muestra, lo más importante es que ésta sea reprensentativa de la población.
Si la población está divida en categorías (estratos), la muestra debe reflejar esas categorías y sus proporciones para evitar sesgos, esto es lo que se denomina como muestreo estratificado (donde cada estrato es la representación de una categoría)

El proceso es el siguiente:

  1. Crear los estratos (basados en las categorías de la fuente de datos )
  2. Calcular las proporciones (la suma de las proporciones debe dar 1)
  3. Definir el tamaño de la muestra
  4. Tomar la muestra según la proporción para cada estrato (categoría)

En python:

proporciones = {
    'Cuautémoc, Hotel': 0.5,
    'Cuautémoc, Museo': 0.2,
    'Venustiano Carranza, Hotel': 0.1,
    'Cuauhtémoc, Mercado': 0.1,
    'Venustiano Carranza, Mercado': 0.1
}

#Crear el dataframe para almacenar la muestra

muestra_estratificada = pd.DataFrame()
tamano_muestra = 10

# filtrar, recorrer los datos y tomar la muestra según proporción

for estrato, proporcion in proporciones.items():
    filtro_estratificado = df[df['estratificado'] == estrato]
    muestra = int(tamano_muestra*proporcion)
    muestra_estrato = filtro_estratificado.sample(n=muestra, random_state=42)
    muestra_estratificada = muestra_estratificada.append(muestra_estrato)

# el resultado será este:
muestra_estratificada

Esta sería la lógica del código:

Filtrar los datos por estratos (categorías), recorrerlos y según su proporción tomar la muestra. El resultado se debe ir almacenando en el dataframe inicial que declaramos

NOTA: El random_state es un número de referencia que utiliza Python para generar la muestra aleatoriamente, se puede cambiar para generar diferentes tipos de muestra (debe ser número entero), si se mantiene, la muestra será la misma.

A diferencia del código de la profe, este toma una muestra más pequeña en relación
a la fuente de datos.

¡saludos!

lo que hace este tipo de muestreo es agarrar el dataframe, lo mapea, lo separa por las categorias o "estratos" que le definas y reescribe las hileras/rows del dataframe para ajustarse a las proporciones que le pediste, aun no entiendo bien porque querer modificar un dataframe a tu gusto si se supone que lo que se debe ahacer es interpretarlo, no ajustarlo a una hipotesis ideal que se ajuste a uno

Hay una imprecisión: El parámetro random_state (en este caso 42) la instructora indica que hace que las filas se tomen de 42 en 42 lo cual no tiene nada que ver con su verdadero comportamiento (pueden verificar que las filas no tienen ese intervalo). Lo que hace es servir de semilla para el generador de números aleatorios y es un parámetro opcional en la función sample.

En el contexto de muestreo, el parámetro “random_state” es utilizado para establecer una semilla para el generador de números aleatorios utilizado en la selección de muestras. Esto asegura que los resultados son reproducibles, ya que si utiliza el mismo valor para “random_state” en dos llamadas diferentes, se seleccionarán las mismas muestras. Sin embargo, si se utiliza un valor diferente para “random_state” en cada llamada, se seleccionarán muestras diferentes.

Si bien el código debería funcionar bien, es mejor comprobar el resultado, aquí una pequeña validación del objetivo

(df_estrat['estratificado'].value_counts() / len(df_estrat)).sort_values(ascending=False)

Cuautémoc,Hotel                0.5
Cuautémoc,Museo                0.2
Venustiano Carranza,Hotel      0.1
Cuauhtémoc,Mercado             0.1
Venustiano Carranza,Mercado    0.1
Name: estratificado, dtype: float64
Entiendo bien lo que quieren demostrar, pero no seria bueno que al implementar la parte del código tratara de poner un poco ya sea que enfatices a los nombres ya que algunas veces no se sabe porque usa ese nombre o tratar de explicar desde el comienzo lo que quería hacer para uno entender mejor antes de que comience a realizar el código
para verificar al final :: ```js (df_estrat['estratificado'].value_counts() / len(df_estrat)).sort_values(ascending=False) ```
Con el metodo \*value\_counts()\* podemos obtener los porcentajes directamente a traves de un parametro llamado \*normalize\*. Por tanto, no es necesario la division por el tamano del dataframe. Se expresa de la siguiente forma`:` ```js (df_p['estratificado'].value_counts(normalize=True)).sort_values(ascending=False) ```

📌 NOTA: En la función data_estratificada al obtener la muestra aleatoria, el parámetro replace=True nos permite repetir rows del DataFrame df_filtrado cuando el total de elementos a tomar (n=ratio_len) es mayor a la longitud del DataFrame, de lo contrario python nos lanzara este error:

En consecuencia obtenemos un nuevo DataFreame con rows repetidos, por ende al final podemos hacer una limpieza de la muestra eliminando aquellos elementos que se duplicaron.

cleaned_df = df_estrat.drop_duplicates(keep="first")
print(f"shape={cleaned_df.shape}")
cleaned_df

Espero este aporte les sea de ayuda 😃

Les comparto mis apuntes en notion: <https://www.notion.so/Muestreo-estratificado-en-python-799d54cd991842b4acd6dc9cea3ce542>
n=ratio\_len da error
**AHORA PUE¡¡¡** Muestreo estraficcado
La proporción es una decisión arbitraria?
Pueden corregir el "Cuautémoc" mal escrito con así: ```python def fix_words(column): for i in range(len(column)): if column[i] == "Cuauhtémoc": column[i] = "Cuautémoc" return column.copy() econdata["delegacion"] = fix_words(econdata["delegacion"]) econdata["delegacion"].value_counts() ```def fix\_words(column):  for i in range(len(column)):    if column\[i] == "Cuauhtémoc":      column\[i] = "Cuautémoc"   return column.copy() econdata\["delegacion"] = fix\_words(econdata\["delegacion"])econdata\["delegacion"].value\_counts()

Hice un codigo similar pero con pequeños cambios que permitern al usuario definir la proporción del tamaño de la muesta.

def data_stratify(df, column_strat, values_strat, frac=0.25, random_state=None):
    df_stratify = pd.DataFrame(columns=df.columns)
    total_size = frac * len(df)
    
    for name, proportion in values_strat.items():
        ratio_len = int(proportion * total_size)
        df_filtrate = df[df[column_strat] == name]
        df_temp = df_filtrate.sample(replace=True, n=ratio_len, random_state=random_state)
        
        df_stratify = pd.concat([df_stratify, df_temp])
    return df_stratify

values_strat = {
    'Cuautémoc,Hotel': 0.5,
    'Cuautémoc,Museo': 0.2,
    'Venustiano Carranza,Hotel': 0.1,
    'Cuauhtémoc,Mercado': 0.1,
    'Venustiano Carranza,Mercado': 0.1
}

df_strat = data_stratify(econdata, 'estratificado', values_strat, frac=0.3, random_state=42)

Los muestreos aleatorio, sistemático y estratificado son tres métodos comunes y ampliamente utilizados en la práctica del muestreo. Sin embargo, no se puede decir que sean los únicos importantes, ya que existen otros métodos de muestreo que también pueden ser relevantes según el contexto y los objetivos de la investigación.

A continuación, te proporciono una descripción de estos tres métodos de muestreo y algunas consideraciones sobre su importancia:

Muestreo Aleatorio: En este método, cada elemento de la población tiene la misma probabilidad de ser seleccionado para formar parte de la muestra. Es un enfoque sencillo y objetivo, que permite obtener muestras representativas de la población. Es ampliamente utilizado y forma la base de otros métodos de muestreo.

Muestreo Sistemático: En este método, se selecciona un elemento de la población al azar y luego se seleccionan los elementos subsiguientes a intervalos fijos. El tamaño del intervalo se determina dividiendo el tamaño de la población entre el tamaño de la muestra deseado. Este método es simple de implementar y puede ser eficiente en términos de tiempo y costos. Sin embargo, puede introducir sesgos si hay un patrón sistemático en la distribución de los elementos.

Muestreo Estratificado: En este método, la población se divide en grupos homogéneos llamados estratos, y luego se selecciona una muestra de cada estrato de manera independiente. El objetivo es asegurar que cada estrato esté representado en la muestra, lo que permite obtener estimaciones más precisas para subgrupos específicos de la población. El muestreo estratificado es particularmente útil cuando hay variabilidad heterogénea dentro de la población.

Aunque estos tres métodos son muy importantes y ampliamente utilizados en el muestreo, existen otros métodos que también pueden ser relevantes dependiendo del contexto y los objetivos de la investigación. Algunos ejemplos incluyen el muestreo por conglomerados, el muestreo por cuotas y el muestreo secuencial. Cada método tiene sus propias ventajas y desventajas, y la elección del método adecuado depende de diversos factores, como la naturaleza de la población, el tamaño de la muestra deseado, los recursos disponibles y los objetivos del estudio.

Costó entender el código pero se logró, gracias a la comunidad por complementar la clase 😄

No busque explicar perfectamente el código, pero ya que me lo escribí para entender mejor, lo dejo por aca (recuerden usar chatgpt apra que les explique funciones y lineas enteras o métodos de alguna libreria:

#Reconfiguramos los datos
#Creamos un nuevo dataframe extrayendo muestras de cada estrato, cumpliendo con las proporciones indicadas
#orden de parametros (BBDD, columna generada, nombres de las divisiones que hicimos, proporción deseada de las divisiones)
def data_estratificada(econdata, nombres_columnas_estrat, valores_estrat, prop_estrat, random_state=None):
    #hacemos un nuevo df con columnas vacias del mismo nombre q econdata
    df_estrat = pd.DataFrame(columns = econdata.columns)
    #variable para seguir la posición en la lista valores_estrat
    pos = -1
    #copiamos las filas tomando como proporción para la cantidad de muestras, a los valores en la lista prop_estrat
    for i in range(len(valores_estrat)):
        pos += 1
        #si es el ultimo estrato
        if pos == len(valores_estrat) -1:
            #ratio_len = 230 - (4?)
            ratio_len = len(econdata) - len(df_estrat)
        else:
            #ratio_len = la proporción = prop_estrat[i] de econdata
            ratio_len = int(len(econdata) * prop_estrat[i])

        #seleccionamos las columnas en "estratificado" que sean iguales a valores_estrat[i]
        df_filtrado = econdata[econdata[nombres_columnas_estrat] == valores_estrat[i]]
        #filtra pudiendo copiar filas, en la proporcion de ratio_len, y con random_state = None implica que el muestreo no será determinista, variando en cada ejecución
        df_temp = df_filtrado.sample(replace=True, n=ratio_len, random_state=random_state)
        #concatena df_estrat y df_temp
        df_estrat = pd.concat([df_estrat, df_temp])
    return df_estrat

El siguiente código me regresa los valores de cada categoría ordenados del que mas veces aparece al que menos, seria una forma de reemplazar valores_estrat pero igual generar uno mismo la lista con los valores nos da un mayor control sobre las proporciones que le asignamos a cada categoría.

econdata[columna_strat].value_counts().index

Resultado final:

(df_estrat['estratificado'].value_counts() / len(econdata)).sort_values(ascending=False)

Muy bueno para dar esas proporciones al final y luego hacer otros estudios con los datos resultantes