The purpose of this project was to explore the raw data of the Marvel Comic Universe (MU) Social Network and analyze the connections between prominent characters based on their shared comic appearances. I visualized these connections through a self-created social network. I then eliminated the comic appearances, applied social network functions to the social network graph I created, and displayed different edge weights to visualize the hero to hero connections.

Extracting Data and Creating Graphs

First, I retrieved raw Marvel Universe (MU) data from the Wolfram Data Repository, which was my main source of data throughout my project. The Marvel heroes were then connected to their specific comic appearances through edges, to condense the data into edges for the social network graph.
ResourceData can be used to retrieve data and EdgeList applied to connect the data:
In[]:=
rawdata=ResourceData["Marvel Universe Social Network"];​​edges=EdgeList@rawdata;
The raw data has labels based on type - either "Hero" or "Comic" - so assigning the data's index numbers and names to both heroes and comics successfully categorized the data.
I used Map and AnnotationValue to extract values of heroes/comics and assign names to raw data:
In[]:=
heroNums=VertexList[rawdata,_?(AnnotationValue[{rawdata,#},"Type"]==="Hero"&)];​​comicNums=VertexList[rawdata,_?(AnnotationValue[{rawdata,#},"Type"]==="Comic"&)];​​heroNames=AnnotationValue[{rawdata,#},"Name"]&/@heroNums;​​comicNames=AnnotationValue[{rawdata,#},"Name"]&/@comicNums;
I had to get the comic appearances of the heroes, which I defined a function for - when I plug a hero's index number in, the function gives me the comics they appeared in. I needed to define a function to find comic appearances so I could use it when creating my social network graph, as I would be able to connect the heroes through their shared comic appearances from the list this function gives me.
I used Part to get the second portion of the edges, as the edges function connects hero index # to the comics they appear in; doing this retrieved a hero's comic appearances when that hero's index number was put in:
In[]:=
getComicAppearances[num_Integer]:=Split[#][[2,1]]&/@Cases[edges,num___]
I associated heroes' names with their index numbers to include all the possible variations of the hero into the index number; ex. Thor, Thor 3D, Thor 4. This was in order to condense the data for one hero into their index number, so slight variations of the hero would still be factored in.
Applying the Association function to heroes' names in the data gets all variations, as well as using StringMatchQ to account for any slight changes in the hero's name:
In[]:=
heroAssociation=Association@@(ToLowerCase@heroNames[[#]]->#&/@Range[Length[heroNames]]);​​heroNameToIndex[name_String]:=DeleteMissing[heroAssociation/@​​Join[{ToLowerCase@name},​​Select[Keys@heroAssociation,StringMatchQ[ToLowerCase@name~~" "~~___]]]]
I extracted a smaller group of main heroes for the social network, rather than trying to find connections between all the characters in the MU; finding heroes' and comics' index numbers and edges was essential for creating a visualization of the social network.
I created/defined many functions that represent index numbers from the raw data, names, and various edges of the main heroes I pulled from the data:
In[]:=
mainHeroes=
Hero Names
;​​mainHeroIndexes=heroNameToIndex/@mainHeroes;​​mainComicIndexes=Map[Flatten,Map[getComicAppearances,heroNameToIndex/@mainHeroes,{2}]];​​mainEdges=Flatten@Table[mainHeroIndexes[[n,1]]#&/@mainComicIndexes[[n]],{n,1,Length[mainHeroIndexes]}];
I then labeled the heroes' index numbers with their names, specifically drawing out a list of 9 main heroes in the MU. These heroes were chosen based on their extensive list of comic appearances, as this indicated popularity in the social universe. This was important to label vertexes on my social network graph with the correct main heroes' names.
The function mainHeroLabels assigns the main heroes' names to their respective index numbers.
In[]:=
mainHeroLabels=
Hero Labels
;
Next, I bolded and adjusted the size of the main heroes' labels to emphasize them on the graph.
Using Style to bold the main heroes on the graph and Map to apply this styling to mainHeroLabels:
In[]:=
styledMainHeroLabels=#[[1]]->Style[#[[2]],Black,Bold,Medium]&/@mainHeroLabels;
Finally, I created my 3D social network graph; vertices featured on the graph were comics and main heroes.
I used HighlightGraph and VertexStyle to change the colors and labels of the vertices on the social network graph; choosing a contrasting color scheme for the 3D vertices was crucial to make them easy to look at:
In[]:=
HighlightGraphGraph3D[mainEdges,VertexLabels->styledMainHeroLabels],​​mainEdges,StylemainEdges,
Pink
,VertexStyle->#[[1]]->
Green
&/@mainHeroLabels​​
Out[]=

Remove Single Appearance Comics

I extended my project by removing single appearance comics, or the comic appearances that were not shared by one or more heroes. This highlighted the direct connections between the heroes as unshared ones were eliminated.
Using Intersection, I found the shared comic appearances between the heroes and deleted all comic appearances except those that were shared.
In[]:=
dualComicIndexes=Table[DeleteDuplicates[Flatten[Table[If[n!=index,Intersection[mainComicIndexes[[index]],mainComicIndexes[[n]]],{}],{n,1,Length[mainComicIndexes]}]]],{index,1,Length[mainComicIndexes]}];
Next I connected heroes' index numbers with the index numbers of the comics that they appeared in through double-sided edges that would make it easy to visualize the connections.
dualEdges connects hero index numbers with comic index numbers with dual edges for when graphing:
In[]:=
dualEdges=Flatten@Table[mainHeroIndexes[[n,1]]#&/@dualComicIndexes[[n]],{n,1,Length[mainHeroIndexes]}];
I made the model 3D to have a more visually appealing and clear social network; .
Using Graph3D and Hue for styling the color scheme and vertex labels:
In[]:=
HighlightGraphGraph3D[dualEdges,VertexLabels->styledMainHeroLabels],​​dualEdges,StyledualEdges,
Pink
,VertexStyle->#[[1]]->
Green
&/@mainHeroLabels
Out[]=

Hero to Hero Connections

After creating an initial visualization of the hero connections, I created an actual social network between the heroes; this meant that comic vertices were deleted and a network of just heroes was left. My first step in this process was creating a function with which I could input a comic and output a list of heroes that appear in that comic, which connected the heroes to each other by grouping them by shared comic appearances.
Creating function getHerosFromComics, using Cases and Part to get the heroes out of the edge connections between a hero and a comic:
In[]:=
getHerosFromComics[comic_]:=Cases[dualEdges,___comic][[All,1]]
Many of the lists were duplicated due to the heroes being in more than one shared comic, so I condensed the previous output to get a unique list of hero connections by deleting such duplicates.
Delete duplicates of the heroes that shared comic appearances:
In[]:=
DeleteDuplicates[getHerosFromComics/@DeleteDuplicates[Flatten[dualComicIndexes]]];
Using the list of connected heroes that I got from the line of code above, I then created direct connections between heroes by connecting two heroes so I could continue making a social network of just heroes.
Divided the hero lists into lists of 2 - using Subsets and Map - so there would be direct connections between the heroes, defining it into function hero2hero:
In[]:=
hero2hero=Partition[Flatten[Subsets[#,{2}]&/@getHerosFromComics/@DeleteDuplicates[Flatten[dualComicIndexes]]],2];
To graph this in a social network, I had to create edges between the two heroes in the lists I created so they could be physically connected in the graph.
hero2heroEdges uses Map to connect the lists of the hero2hero with a double-sided edge:
In[]:=
hero2heroEdges=#[[1]]#[[2]]&/@hero2hero;
I finally finished this compact social network that had direct connections between the heroes (as it excluded the vertices representing comics).
I made a 3D representation of the direct social network with just the main heroes, with styled vertices:
In[]:=
Graph3DDeleteDuplicates[hero2heroEdges],VertexLabels->styledMainHeroLabels,​​VertexStyle->
Green

Out[]=

Weighting Edges

The next extension that I completed for my project was visually representing the different edge weights of the social network through a color scale; this displayed the varying scale of connections between the heroes.
Using the Counts function on hero2heroEdges to count the amount of times the heroes were connected:
Next, I created a 2D model of the social network that showed the differing edge weights through the thickness of the connecting lines.
Use styling functions to make the vertices and varying thickness visible; using heroEdgeWeights to compute the different thicknesses:
Although the 2D plot shown above displayed the edge weights and thus the varying social connections between the main heroes, I preferred the 3D social network. Thickness would not work on the 3D plot, however, so I decided to represent the differing edge weights by color.
Thickness was replaced with Hue, on a varying color scale that easily displays the heroes' edge weights:
I added a color scale above the final social network that clarified the significance of the different edge colors: as shown below, fewer shared comics meant red/orange/yellow edges; more shared comics meant dark blue/purple/pink edges.
Using Column and Style functions to create and position the color scale guide:

Social Network Analysis

Cliques

I extended the basis of my project, or the social network, by using Social Network functions - starting with finding cliques in the graph (Thor, Hulk, Dr. Strange, Quicksilver).
Using FindClique and defining functions to find the clique:
I then labelled the four main heroes in the clique so I could use their names as vertex labels on the social network.
Using Map and Keys, I made an association between the heroes in the clique and their index numbers:
Next, I styled the clique hero labels for visibility on the social network.
I made an association of a hero's index number to their bolded name, using Map to apply this styling to the function cliqueHeroLabels that I previously defined:
I connected the clique heroes together so it would be visualized on the graph, serving as a model of my finished extension.
I applied Subsets to the list of clique heroes to find all the possible clique heroes' direct connections with another hero:
Using all of my previous work, I created a visualization of the clique in the original 3D social network.
Styling the edges of the clique to stand out from the rest of the visualized network:

Communities

I found communities within my social network graph; this was a suggested function to explore social networks.
I found the communities in the graph of my MU social network:
I then divided the list into the two graph communities, so I could highlight them on the overall social network graph later.
Using Part to separate the communities; defining the divided graph communities into functions to be used later:
The next step was to create functions to contain the edges of the graph communities so that I could style them in the social network.
Defining two functions, I used Map and Subsets to pull the edges I needed out of the data:
My final step for this extension was to physically display the graph communities onto the social network.
I used my previously defined functions to easily highlight the newly discovered communities; mainly using Table and Style functions:

Ranking the Vertices Based on Amount of Connections

The final extension of my project was ranking vertices based on their amount of connections to other vertices; this was included as a function of exploring social networks.
Getting a list of the vertices in the social network; ranking them using DegreeCentrality and Ordering (based on their connections to other vertices):
I completed this extension by switching the heroes' index numbers out with their names, just to clarify the order of the heroes.
I used the variable for the degree centralities to put the main heroes in order of their various connections:

Future Directions

In future work regarding this project, I would like to create a larger social network with more heroes besides the main ones. I believe also exploring connections between the data labelled "villains" and heroes - due to time constraints, I focused my project on heroes; however, I think including villains into this project would be very interesting.

Acknowledgements

First of all, I would like to thank Simeon Buttery, who was my mentor throughout my whole project and encouraged me to learn so much about the Wolfram Language; this project definitely could not have been done without him. Thank you to the directors of the Wolfram High School Research Program, Eryn, Rory, and Megan, who put so much effort and time into this amazing program; finally, thank you to Stephen Wolfram for providing this wonderful opportunity to high school students.

CITE THIS NOTEBOOK

Visualize and analyze the Marvel Universe social network​
by Jaimie Park​
Wolfram Community, STAFF PICKS, July 13, 2023
​https://community.wolfram.com/groups/-/m/t/2963948