Aesthetic mappings created with aes. If specified and inherit_aes=True, it is combined with the default mapping for the plot. You must supply mapping if there is no plot mapping.
The data to be displayed in this layer. If None, the data from from the ggplot() call is used. If specified, it overrides the data from the ggplot() call.
Whether this layer should be included in the legends. None the default, includes any aesthetics that are mapped. If a bool, False never includes and True always includes. A dict can be used to exclude specific aesthetis of the layer from showing in the legend. e.g show_legend={'color': False}, any other aesthetic are included by default.
elements = pd.read_csv("data/elements.csv")elements.head()
atomic number
symbol
name
atomic mass
CPK
electronic configuration
electronegativity
atomic radius
ion radius
van der Waals radius
...
EA
standard state
bonding type
melting point
boiling point
density
metal
year discovered
group
period
0
1
H
Hydrogen
1.00794
#FFFFFF
1s1
2.20
37.0
NaN
120.0
...
-73.0
gas
diatomic
14.0
20.0
0.00009
nonmetal
1766
1
1
1
2
He
Helium
4.002602
#D9FFFF
1s2
NaN
32.0
NaN
140.0
...
0.0
gas
atomic
NaN
4.0
0.00000
noble gas
1868
18
1
2
3
Li
Lithium
6.941
#CC80FF
[He] 2s1
0.98
134.0
76 (+1)
182.0
...
-60.0
solid
metallic
454.0
1615.0
0.54000
alkali metal
1817
1
2
3
4
Be
Beryllium
9.012182
#C2FF00
[He] 2s2
1.57
90.0
45 (+2)
NaN
...
0.0
solid
metallic
1560.0
2743.0
1.85000
alkaline earth metal
1798
2
2
4
5
B
Boron
10.811
#FFB5B5
[He] 2s2 2p1
2.04
82.0
27 (+3)
NaN
...
-27.0
solid
covalent network
2348.0
4273.0
2.46000
metalloid
1807
13
2
5 rows × 21 columns
Alter the data types of the information that will be plotted. This makes it convenient to work with.
elements["group"] = [-1if g =="-"elseint(g) for g in elements.group]elements["bonding type"] = elements["bonding type"].astype("category")elements["metal"] = elements["metal"].astype("category")elements["atomic_number"] = elements["atomic number"].astype(str)
The periodic table has two tables, a top and bottom. The elements in the top have groups, and those in the bottom have no groups. We make separate dataframes for both – they have different alignments.
top = elements.query("group != -1").copy()bottom = elements.query("group == -1").copy()
The top table is nice and well behaving. The x location of the elements indicate the group and the y locations the period.
top["x"] = top.grouptop["y"] = top.period
The bottom table has 2 rows, with the atomic number increasing to the right. We create an x based on the atomic number and add a horizontal shift. As the dataframe is ordered by atomic number, the operation is easier. The bottom elements are labelled with a “period”. We add a vertical shift to give us a good y location that gives the appearance of two tables.
We will be plotting using tiles and we want to have some space between the tiles. We have set the x and y locations above to take up a unit of space. To get a good effect, the tile dimensions should be less than 1.
The table upside down. We could have been more careful when creating the y locations since the periods are drawn in descending order. But, we can fix that with a reverse scale.
There are four pieces of text that we shall add to the tiles, that is 4 geom_text additions. As we have two tables, that comes to 8 geom_text additions. When any geom is added to a ggplot object, behind the scenes a layer is created and added. We can create a group of layers that can be added to a ggplot object in one go using a list.
We use a function that accepts a dataframe, and returns a list of geoms.
It is crowded in there and the tiles do not have equal dimentions. Use the theme create a larger figure. coord_equal give us equal units along the axes, this makes the tiles square.
It is has all the information we want, except one for complication. Elements Lu and Lr also belong in the bottom table. One way to show this duality is to have tiles with two colors split horizontally.
The colors are determined by the metal field, and we know the x and y locations. We create a dataframe with this information to create a half-tile. A half-tile is centered at the quarter mark.
Add the group number along the top most row of each column, and period number along the left side of the top table.
For the period number, we set the breaks on the y scale.
# The location of the group number is the top most (and therefore smallest period)# element with the groupgroupdf = top.groupby("group").agg(y=("period", "min")).reset_index()
After we set the x and y positions in th the top and bottom dataframes, we could have concatenated them back together. Then, that Layers trick would not save us much.
Pro tip: Save the plot as a pdf.
Annotated Heatmap
Conditinous data recorded at discrete time intervals over many cycles
# We use 'factor(year)' -- a discrete -- instead of 'year' so that all the years# are displayed along the x-axis.# The .95s create spacing between the tiles.( ggplot(flights, aes("factor(year)", "month", fill="passengers"))+ geom_tile(aes(width=0.95, height=0.95))+ geom_text(aes(label="passengers"), size=9))
That looks like what we want, but it could do with a few tweaks. First the contrast between the tiles and the text is not good for the lower passenger numbers. We use pd.cut to partition the number of passengers into two discrete groups.