¿Existe una función de pandas para "aplicar en forma cruzada" un marco de datos consigo mismo utilizando una función personalizada?

2020-06-30 python pandas

Dado un Pandas DataFrame como este:

|------|-------|
|col1  |col2   |
|------|-------|
|a1    |abc    |
|a2    |bcd    |
|a3    |kfs    |
|------|-------|

¿Existe una función para crear eficientemente (el DataFrame real tiene> 10,000 filas) crear una matriz de la siguiente manera, con el uso de una función personalizada para determinar los valores de los campos numéricos?

|------|-------|------|-------|
|      |a1     |a2    |a3     |
|------|-------|------|-------|
|a1    |1.000  |0.362 |0.643  |
|a2    |0.362  |1.000 |0.364  |
|a3    |0.643  |0.364 |1.000  |
|------|-------|------|-------|

Lo que probé hasta ahora:

  • Convertir el DataFrame en una lista y usar una comprensión de lista anidada. Eso, sin embargo, está tomando demasiado tiempo en cuanto a rendimiento.
  • Usando sklearn pairwise_distance con mi función personalizada definida como una métrica. Mismo problema de rendimiento aquí.

Finalmente, se generará la siguiente representación:

|------|--------------------------------------|
|a1    |{a1: 1.000}, {a2: 0.362}, {a3: 0.643} |
|a2    |{a1: 0.362}, {a2: 1.000}, {a3: 0.364} |
|a3    |{a1: 0.643}, {a2: 0.364}, {a3: 1.000} |
|------|--------------------------------------|

Answers

Una forma de hacerlo sería crear un producto cruzado entre todos los valores posibles de col1, ejecutar el cálculo para cada par y luego pivotar:

# dummy data
df = pd.DataFrame({
    "col1": [f"a_{i}" for i in range(5)], 
    "col2": range(5)})

# the following dataframe is produced. We're now looking for a way to 
# run some calculation for each combination of col1 x col1
  col1  col2
0  a_0     0
1  a_1     1
2  a_2     2
3  a_3     3
4  a_4     4

df = pd.merge(df.assign(dummy=1), df.assign(dummy=1), on = "dummy").drop("dummy", axis=1)
df["res"] = df.col2_x * df.col2_y
pd.pivot_table(df, index="col1_x", columns="col1_y", values = "res")

El resultado es:

col1_y  a_0  a_1  a_2  a_3  a_4
col1_x                         
a_0       0    0    0    0    0
a_1       0    1    2    3    4
a_2       0    2    4    6    8
a_3       0    3    6    9   12
a_4       0    4    8   12   16

Related