Mostrando las entradas con la etiqueta grafos. Mostrar todas las entradas
Mostrando las entradas con la etiqueta grafos. Mostrar todas las entradas

viernes, 31 de mayo de 2024

Tutorial. Grafos en la cocina (II)

Grafos sabrosos

Continuo con el análisis de redes de ingredientes y platos de la cocina venezolana. En este post exploro los platos con mayor nivel de inermediación. Es decir,con ingredientes que están presentes en diferentes comunidades de platos y constituyen, por decirlo así, ingredientes que le confieren su particularidad a la culinaria venezolana. Posteriormente analizo las comunidades de platos que se conforman en función de los ingredientes que los componen.


Segunda parte. Intermediación y comunidades


Analizo primero cuál es el plato con mayor nivel de intermediación y, luego, las posibles comunidades de acuerdo con los ingredientes. usaré nuevamente todos los platos, pero para facilitar la visualización, me quedaré con los nodos con un grado de intermediación mayor a la mediana:

par(bg="gray98",mar=c(1,1,1,1)) 
# visualizo
plot(todosb)

De acuerdo con la frecuencia de los ingredientes que componen los diversos platos que he tomado para el presente tutorial, los platos de la cocina venezolana se relacionan de la siguiente manera:

Fig.1 - Ingredientes según nivel de intermediación

Nota:Posiblemente no es ninguna sorpresa: los platos con mayor grado de intermediación son aquellos que fungen como acompañantes/segundos platos/postres o platos especiales. Algo que el algorritmo logra capturar, pues no se le ha impuesto a la data ningún tipo de clasificación previa.

Visualizo las comunidades en los nodos con un grado mayor a la mediana:

comunidades<- cluster_louvain(todos1)
      modularity(comunidades)

##      
## [1] 0.05465422


 #pido la particion para generar comunidades 
todos_comunidades<- membership(comunidades)
      


par(bg="gray98",mar=c(1,1,1,1))
 #visualizo 
plot(comunidades, todos1)
      

Fig.2 - Platos según comunidades

Nota:detectan tres comunidades. La sobreposición de los bloques nos confirman lo que señalabamos inicialmente: los 93 platos se elaboran a partir de un grupo reducido de ingredientes.

si visualizamos los platos que comparten menos ingredientes, veremos que, de existir, esta sobreposición no será tan acentuada:


par(bg="gray98",mar=c(1,1,1,1))
 #visualizo 
comunidades2<- cluster_louvain(todos2)
plot(comunidades2, todos2)
     

Fig.3 - Platos según comunidades

Nota:En estos platos hay dos comunidades. El algorritmo logra diferenciar entre postres o comidades que incorporan sabor dulce/huevos, y lo que serían platos que llevan menos dulce y más sal. De allí que el plátano dulce, por ejemplo, pertezca a una comunidad diferente a la del platano sancochado.

Observando las comunidades pero sin los bloques:

Fig.4 - Comunidades

Nota:Las comunidades parecen agruparse, grosso modo, en torno a platos elaborados con harinas/granos/cochino; carnes(blancas, rojas) y sopas/sancochos/cremas. Esta agrupación la visualizaremos mejor cuando observemos los ingredientes.

Tutorial. Grafos en la cocina (I)

Grafos sabrosos

En este trabajo se propone una metodología para analizar la cocina venezolana a través de redes de ingredientes. La metodología se basa en la construcción de grafos a partir de las recetas de platos típicos, utilizando como nodos los ingredientes y como aristas las relaciones de co-ocurrencia entre ellos. Se pretende identificar patrones de uso de ingredientes, relaciones de complementariedad y grupos de platos con características similares.

Metodología

  1. Recolección de datos:
    • Se utilizarán como fuente de datos las recetas de platos venezolanos publicadas en la obra "Cocinar a la venezolana" (El Nacional, 2001).
    • Se extraerá la información sobre los ingredientes de cada plato, incluyendo su tipo (por ejemplo, carne, vegetal, cereal) y, en la medida de lo posible, su variedad específica (por ejemplo, queso blanco duro, queso blanco semi-duro, queso blanco blando).

    La información obtenida es limitada a la fuente utilizada, por consiguiente, el análisis podría variar con otras fuentes.

  2. Construcción de redes. Se crearán dos tipos de redes:
    • Red de platos: Los nodos serán los platos y las aristas representarán la co-ocurrencia de ingredientes entre ellos. El peso de la arista se asociará a la frecuencia de co-ocurrencia.
    • Red de ingredientes: Los nodos serán los ingredientes y las aristas representarán la co-ocurrencia en los mismos platos. El peso de la arista se asociará a la frecuencia de co-ocurrencia.
  3. Análisis de redes.
    • Se aplicarán métricas de redes para caracterizar la estructura y conectividad de las redes.
      • Red de platos: Se analizará el grado de centralidad de los platos, identificando aquellos que son más importantes en la red por su conexión con otros platos. También se pueden identificar comunidades de platos con características similares.
      • Red de ingredientes: Se analizará la centralidad de los ingredientes, identificando aquellos que son más utilizados en la cocina venezolana. También se pueden identificar grupos de ingredientes que se utilizan frecuentemente juntos.
    • Se utilizarán técnicas de visualización para representar las redes y facilitar su interpretación.

Distribuiré este análisis en tres o cuatro posts. Este el el primero. Es importante dejar claro quen o poseo los derechos de autor del material consultado. Este análisis tiene fines educativos.


Primera parte. Grafo de los platos e ingredientes de la cocina venezolana


De acuerdo con la frecuencia de los ingredientes que componen los diversos platos que he tomado para el presente tutorial, los platos de la cocina venezolana se relacionan de la siguiente manera:

par(bg="gray98",mar=c(1,1,1,1)) 
# visualizo
plot(d$g2)
Fig.1 - Relación entre los platos de acuerdo con los ingredientes empleados.

Esta primera imagen nos sugiere que hay una diversidad de platos elaborados a partir de un mismo grupo de ingredientes.Verifico inspeccionando los algunos indicadores:

estructura(e$g2
)
##      Indicadores   valor
## 1          nodos   93.00
## 2        aristas 3310.00
## 3       densidad    0.77
## 4       diametro    4.00
## 5   long.med.cam    1.23
## 6    grado medio   71.18
## 7    modularidad    0.03
## 8 coefic.cluster    0.88


Hay 93 platos y 3325 aristas. Es un grafo casi completo, en el que de un plato, y sus ingredientes, podemos pasar a otros (es decir, con pequeña variación en los ingredientes y a partir del "plato A" podemos obtener el "plato B"). De allí que sea fácil agrupar estos platos en conglomerados (clusters), tal como nos sugiere el coeficiente de cluster.

Todo lo anterior podría ser, por un lado, una gran fortaleza. La cocina venezolana sería la muestra de una gran creatividad. Con pocos ingredientes se logra elaborar una variedad de platos y sazones. Sin embargo, esto podría ser también una debilidad. La escasez de los ingredientes básicos durante un lapso prolongando sometería a prueba la identidad nacional. Significaría un reto a la fuerza de la costumbre, que no contaría, al menos en el corto plazo, con la capacidad para sustituir esos ingredientes y obtener el sabor acostumbrado. El sabor de casa.

Quiero observar este gráfico tomando la mediana de los vinculos como referencia:

 	
 		# me quedo con nodos con grado mayor a la mediana
 	

todos1 <- delete.vertices(e$g2, V(e$g2)[degree(e$g2) < median(degree(e$g2))])

# selecciono solo los nodos con grado menor o igual a la mediana

todos2 <- delete.vertices(e$g2, V(e$g2)[degree(e$g2) >= median(degree(e$g2))])

Visualizamos estos dos subgrafos

 
 # me quedo con nodos con grado mayor a la mediana
 par(bg="gray15",mar=c(1,1,1,1))
plot(todos1)
                      
  
Fig.2 - Platos con grado mayor o igual a la mediana.

Nota:Los platos que comparten un mayor número de ingredientes son, efectivamente, platos que podrían considerarse de consumo diarios o, en algunos casos, de platos especiales (fines de semana/ festividades). Nótese que el mondongo comparte ingredientes particularmente con la ensalada de gallina, fondo de aves, hervido de res, carne mechada, corbullón de mero, pargo relleno, bollos pelones, pollo al horno y arepas. Si faltan ingredientes relacionados con el mondongo, significa que tampoco se podría elaborar, parcial o totalmente, ninguno de esos otros plato

Fig.3 - Platos con grado menor a la mediana.

Nota: El segundo grupo de platos se relaciona, generalmente, con acompañantes (entradas/segundos platos/postres) así como aderezos o platos muy específicos, especialmente de algunas regiones. Paradójicamente, estos platos sí podrían dejarse de lado sin mucha dificultad, pero son los menos centrales en la cocina venezolana, de acuerdo con la fuente que he consultado.

La escasez de sólo un grupo de ingredientes, entonces, parece generar un efecto cascada en la ausencia de platos acostumbrados en la mesa del venezolano. Un pequeño grupo de ingredientes pareciera impedir la posibilidad de que se elaboren varios platos.

jueves, 30 de mayo de 2024

Tutoriales. Grafos (redes)

Tipos de grafos

De acuerdo con el tipo de relación que se mide en el grupo de actores analizados, los grafos pueden ser binarios, signados, u ordinales. Los grafos binarios reportan si existe o no una relación; los grafos signados nos indican si la relación es negativa, neutra y positiva (-1, 0, 1);en tanto que los grafos con relaciones ordinales nos indican la intensidad de la relación. También es posible tener grafos cuyas relaciones sean valoradas con números reales. Por ejemplo las magnitudes económicas en las relaciones comerciales entre dos actores, la frecuencia con la que ocurre la relación, etc.


Cargo la data y el paquete necesario

load("D:/pRedes.RData")
require(igraph)

Elaboro un ejemplo de relaciones binarias:

#creo una matriz binaria
	(l <- matrix(rep(seq(0,1),8), 4, byrow=T))
##      [,1] [,2] [,3] [,4]
## [1,]    0    1    0    1
## [2,]    0    1    0    1
## [3,]    0    1    0    1
## [4,]    0    1    0    1
# creo nombres para las columnas y las filas
	rownames(l)<-c(LETTERS[1:4]) 
	colnames(l)<-c(LETTERS[1:4])

	# creo el grafo con la funcion graph.adjacency porque se trata de una matriz cuadrada
         
	g <-graph.adjacency(l, diag=FALSE)

# visualizo
plot(g)

En este grafo se observa que los dos nodos (puntos) importantes por las relaciones que tienen son los nodos "B" y "D". Los otros dos nodos no se relacionan entre sí y, prácticamente, dependen de los dos nodos anteriores para "enterarse" u obtener lo que quiera que sea lo que el tipo de relación provee.

Veamos ahora un ejemplo con relaciones signadas. Se distinguirá las relaciones (negativas o positivas) con el color y con el tipo de línea:

# genero una matriz
l <- matrix(rep(seq(-1,1), 48), 12, byrow = T)
l
##       [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
##  [1,]   -1    0    1   -1    0    1   -1    0    1    -1     0     1
##  [2,]   -1    0    1   -1    0    1   -1    0    1    -1     0     1
##  [3,]   -1    0    1   -1    0    1   -1    0    1    -1     0     1
##  [4,]   -1    0    1   -1    0    1   -1    0    1    -1     0     1
##  [5,]   -1    0    1   -1    0    1   -1    0    1    -1     0     1
##  [6,]   -1    0    1   -1    0    1   -1    0    1    -1     0     1
##  [7,]   -1    0    1   -1    0    1   -1    0    1    -1     0     1
##  [8,]   -1    0    1   -1    0    1   -1    0    1    -1     0     1
##  [9,]   -1    0    1   -1    0    1   -1    0    1    -1     0     1
## [10,]   -1    0    1   -1    0    1   -1    0    1    -1     0     1
## [11,]   -1    0    1   -1    0    1   -1    0    1    -1     0     1
## [12,]   -1    0    1   -1    0    1   -1    0    1    -1     0     1
# etiqueto
rownames(l)<-c(LETTERS[1:12]) 
colnames(l)<-c(LETTERS[1:12])
g <-graph.adjacency(l, diag=FALSE, weighted = TRUE)

Coloco atributos

# creo un vector para luego colorear las aristas según
# el tipo de relación presente, negativa o positiva

colores <-ifelse(E(g)$weight < 0, "red", "blue")

# genero un vector que me permita diferenciar las aristas
# segun el tipo de relacion, negativa, linea discontinua
tipos <-ifelse(E(g)$weight < 0, "dashed", "solid")
E(g)$lty <- tipos
E(g)$color <- colores
V(g)$color <- "#8B008B"
V(g)$frame.color <- NA
V(g)$label.color <- "white"

Visualizo

plot(g)

Si, por ejemplo, el tipo de relación que se modela con este grafo es la simpatía y antipatía en un contexto dado, se vería fácilmente que, aparentemente, predominan la antipatía en ese contexto.

Las relaciones ordinales y también las que se basan en múmeros reales permiten distinguir la intensidad o el peso de la relación. Escogeré, ademas, que esa intensidad se observe no sólo con el grosor de las líneas sino también con la intensidad del color.

# genero la matriz
m <- matrix(sample(rep(1:4, 300), 144), 12)
m[, c(5, 8)]<-c(0,0,0,4,0,2,0,1,0,0,1,1)
m[, c(1, 12)]<-c(0,0,0,0,0,2,0,0,0,0,1,1)
m[, c(3, 7)]<-c(0,1,0,0,0,2,0,0,0,4,1,1)
m[, c(6, 11)]<-c(4,1,0,0,3,2,0,0,0,4,1,1)
# etiqueto
rownames(m)<-colnames(m)<-c(LETTERS[1:12])
g <-graph.adjacency(m, diag=FALSE, weighted = TRUE)

# colores de las aristas segun el rango
colores<-E(g)$weight
colores<-ifelse(colores ==1, "gray90", colores)
colores<-ifelse(colores ==2, "gray60", colores)
colores<-ifelse(colores ==3, "gray30", colores)
colores<-ifelse(colores ==4, "gray15", colores)

E(g)$width<- E(g)$weight
E(g)$arrow.size <-.9
E(g)$color <- colores
V(g)$color <- "#8B008B"
V(g)$frame.color <- NA
V(g)$label.color <- "white"
plot(g)

Elaboro ahora un ejemplo con data real. He obtenido información sobre a)los principales aereopuertos del país y las ciudades a las que sirven; b)los dueños de las tierras (antiguas haciendas) que posteriormente se transformaron en las urbanizaciones de Caracas, así como los constructores de esas urbanizaciones.

aer<-table(aereopuertos$ciudadserv, aereopuertos$estado)

g1 <-graph_from_incidence_matrix(aer, directed=TRUE, 
                                 mode="in", weighted = TRUE)
par(bg="gray15",mar=c(1,1,1,1)) 

plot(g1, edge.width=0.9, vertex.size=3, 
      edge.arrow.size=0.6,
      vertex.color= "#BF3EFF",
     vertex.frame.color= NA,
     asp=FALSE, vertex.label.color = "#C1FFC1")


Dueños de las tierras en las que se construyeron posteriormente urbanizaciones en la gran Caracas

terminos <-1:61
columnas <-62:97
colores <-ifelse(caracas.urbaniacion$ubicación =="distrito federal", "#98F5FF", "#E9967A")

m2 <-table(caracas.urbaniacion$urbanizacion,
           caracas.urbaniacion$propietario)
g2 <-graph_from_incidence_matrix(m2, directed=TRUE, 
                                 mode="in", weighted = TRUE)
V(g2)$size[terminos] <- 4
# vertices de columnas
V(g2)$size[columnas] <- 5
V(g2)$color[terminos] <- colores
V(g2)$color[columnas] <- "#F0FFFF"
# colores frame
V(g2)$frame.color[terminos] <-  NA
V(g2)$frame.color[columnas] <- NA
# etiquetas
V(g2)$label.color[terminos]<-"#FFF8DC"
V(g2)$label.color[columnas]<-"#008B8B"
V(g2)$label.family[columnas] <-"mono"
V(g2)$label.cex[terminos]<-0.9
E(g2)$arrow.width <-.45
E(g2)$arrow.size <-.9
par(bg="gray15",mar=c(1,1,1,1)) 

plot(g2)


Quien construyó

m3 <-table(caracas.urbaniacion$urbanizacion,
           caracas.urbaniacion$urbanizador)
m31 <- m3 %*% t(m3)



g <- graph_from_adjacency_matrix(m31, mode="undirected",
                                 diag = FALSE,
                                 weighted = "TRUE"
                                 )
g0 <- delete.vertices(g,
                      V(g)[degree(g)==0]) 

E(g0)$arrow.width <-.45
E(g0)$arrow.size <-.9
V(g0)$color <- "#F0FFF0"

# colores frame
V(g2)$frame.color <-  NA

# etiquetas
V(g0)$label.color<-"#BFEFFF"

V(g2)$label.cex<-0.9
par(bg="gray15",mar=c(1,1,1,1)) 
plot(g0,vertex.size=2, 
     layout= layout.fruchterman.reingold, 
     asp=FALSE)