Reputation: 2421
I'm using Google Colab for learning Python. In this Google Colab notebook I've built for demostration, I was able to get some JSON data and visualize it with Altair.
This is the chart image I got so far - you can interact with the data in the linked Google Colab notebook or directly in the vega-editor ready with the sample data:
Below is the explanation of the data I have and what I want to show:
In Yu-Gi-Oh! TCG, cards came from a certain card set. In each card set are Monster, Spell and Trap cards - as well another type of cards like: Link Monsters, XYZ monsters, etc.
A normal JSON structure of a monster card (- for this purpose - has ATK and DEF) has the following JSON structure:
{
"id":89631139,
"name":"Blue-Eyes White Dragon",
"type":"Normal Monster",
"atk":3000,
"def":2500,
"level":8,
"race":"Dragon",
"attribute":"LIGHT",
"archetype":"Blue-Eyes"
}
But, a non-monster card (i.e. a spell card) has no values neither in ATK and DEF attributes:
Example:
{
"id":35261759,
"name":"Pot of Desires",
"type":"Spell Card",
"race":"Normal",
"archetype":"Greed"
}
I want to visualize in the chart each card that comes in the card set and - while the cursor is on a point (hover), it will show the details of the card like, (Name, ATK, DEF (if any) and the Type of card).
Example of desired tooltip:
After some trial and error, research and read the documentation, I'm facing the following issues and wondering if the results I'm looking are possible:
Image 1:
In "image 1", the card called "Pot of Desires" is a Spell Card = it doesn't have ATK or DEF, I've configured the chart with the invalid property for shown Nulll / None / NaN values) and Altair sets 0 as default to those missing values.
The expected output in (for a non-monster card) would be:
Name: Pot of Desires
Type: Spell Card
The expected output in (for a monster card) would be:
Name: Blue-Eyes White Dragon
ATK: 3000 - DEF: 2500
Type: Normal Monster
The expected output in (for a link monster card = has ATK
, but no DEF
) would be:
Name: Proxy Dragon
ATK: 3000
Type: Link Monster
I want to condition how to build the tooltip in these scenarios, it is possible?
Upvotes: 0
Views: 2729
Reputation: 2421
Thanks to @joelostblom's answer, my case scenario is not possible - yet - let's hope this scenario could be more common in order to raise more attention of the pull request/feature I've created - https://github.com/vega/vega-lite/issues/7811.
Meanwhile, the accepted answer is: is not possible, but, I'll checking for new answers and possible solutions.
That being said, I decide to check further and share my findings here:
Here are the results I mentioned:
The Python code of the previous chart is as follows:
# V.2 of the chart/graph:
alt.Chart(df).mark_point(size=200, filled=True, invalid=None, tooltip={'content': 'data'}).encode(
x={"field": "def", "type": "quantitative", "title": "DEF"},
y={"field": "atk", "type": "quantitative", "title": "ATK"},
color={"field": "type", "type": "nominal", "title": "Types of cards"},
shape="type"
).properties(
title={
"text": ["Cardset: " + cardSetName],
"subtitle": ["Here is shown the " + str(len(df.index)) + " card" + ('s' if len(df.index) > 1 or str(len(df.index)) == 0 else '') + " contained in the cardset."]
}
).transform_calculate(
Name = "datum.name",
Type = "datum.race + ' ' + ((substring(datum.type, datum.type.length-1, datum.type.length) == 's') ? substring(datum.type, 2, datum.type.length-1) : substring(datum.type, 2, datum.type.length))",
ATK_DEF = "isValid(datum.atk) ? '' + datum.atk + (isValid(datum.def) ? '/' + datum.def : '') : 'N/A'"
).interactive()
tooltip={'content': 'data'}
configuration. If there would be a way to declare the fields to use only in the tooltip, this scenario would be possible with Vega/Altair.Here, I share, the code you can copy/paste in the Vega Editor for try it yourself.
N.B. This is the direct vega-editor link with the sample data.
VEGA-LITE Code:
{
"config": {"view": {"continuousWidth": 400, "continuousHeight": 300}},
"data": {"name": "data-5583486ec9c6448394a7b9390873045c"},
"mark": {
"type": "point",
"filled": true,
"invalid": null,
"size": 200,
"tooltip": {"content": "data"}
},
"encoding": {
"color": {"type": "nominal", "field": "type", "title": "Types of cards"},
"shape": {"type": "nominal", "field": "type"},
"x": {"type": "quantitative", "field": "def", "title": "DEF"},
"y": {"type": "quantitative", "field": "atk", "title": "ATK"}
},
"selection": {
"selector149": {
"type": "interval",
"bind": "scales",
"encodings": ["x", "y"]
}
},
"title": {
"text": ["Cardset: 2017 Mega-Tins"],
"subtitle": ["Here is shown the 8 cards contained in the cardset."]
},
"transform": [
{"calculate": "datum.name", "as": "Name"},
{
"calculate": "datum.race + ' ' + ((substring(datum.type, datum.type.length-1, datum.type.length) == 's') ? substring(datum.type, 2, datum.type.length-1) : substring(datum.type, 2, datum.type.length))",
"as": "Type"
},
{
"calculate": "isValid(datum.atk) ? '' + datum.atk + (isValid(datum.def) ? '/' + datum.def : '') : 'N/A'",
"as": "ATK_DEF"
}
],
"$schema": "https://vega.github.io/schema/vega-lite/v4.8.1.json",
"datasets": {
"data-5583486ec9c6448394a7b9390873045c": [
{
"id": 89631139,
"name": "Blue-Eyes White Dragon",
"type": "2 Normal Monsters",
"desc": "This legendary dragon is a powerful engine of destruction. Virtually invincible, very few have faced this awesome creature and lived to tell the tale.",
"atk": 3000,
"def": 2500,
"level": 8,
"race": "Dragon",
"attribute": "LIGHT",
"archetype": "Blue-Eyes"
},
{
"id": 46986414,
"name": "Dark Magician",
"type": "2 Normal Monsters",
"desc": "The ultimate wizard in terms of attack and defense.",
"atk": 2500,
"def": 2100,
"level": 7,
"race": "Spellcaster",
"attribute": "DARK",
"archetype": "Dark Magician"
},
{
"id": 26920296,
"name": "Dreamland",
"type": "2 Spell Cards",
"desc": "This card can activate these effects depending on the monster card types on the field.\n● Fusion: Once per turn, if a monster(s) is sent from your hand or field to the GY by a card effect (except during the Damage Step): You can draw 1 card.\n● Synchro: When a monster(s) is Normal or Special Summoned (except during the Damage Step): You can increase their Levels by 1.\n● Xyz: Once per turn, during your End Phase: Destroy the monster(s) on the field with the highest Level.\nYou can only activate 1 \"Dreamland\" per turn.",
"atk": null,
"def": null,
"level": null,
"race": "Field",
"attribute": null,
"archetype": null
},
{
"id": 80532587,
"name": "Elder Entity N'tss",
"type": "1 Fusion Monster",
"desc": "1 Synchro Monster + 1 Xyz Monster\nMust be Special Summoned (from your Extra Deck) by sending the above cards you control to the GY. (You do not use \"Polymerization\".) Once per turn: You can Special Summon 1 Level 4 monster from your hand. If this card is sent to the GY: You can target 1 card on the field; destroy it. You can only Special Summon \"Elder Entity N'tss(s)\" once per turn.",
"atk": 2500,
"def": 1200,
"level": 4,
"race": "Fairy",
"attribute": "LIGHT",
"archetype": null
},
{
"id": 23085002,
"name": "Number 68: Sanaphond the Sky Prison",
"type": "2 XYZ Monsters",
"desc": "2 Level 8 monsters\nGains 100 ATK and DEF for each monster in the GYs. Once per turn: You can detach 1 material from this card; until the end of your opponent's next turn, this card cannot be destroyed by card effects, also neither player can Special Summon monsters from the GYs.",
"atk": 2100,
"def": 2700,
"level": 8,
"race": "Rock",
"attribute": "DARK",
"archetype": null
},
{
"id": 59479050,
"name": "Number 71: Rebarian Shark",
"type": "2 XYZ Monsters",
"desc": "2 Level 3 monsters\nOnce per turn, if this card has material: You can target 1 \"Number\" Xyz Monster in your GY, except \"Number 71: Rebarian Shark\"; Special Summon it, and if you do, attach 1 material from this card to it. If this card is sent to the GY: You can choose 1 \"Rank-Up-Magic\" Spell from your Deck and place it on top of your Deck.",
"atk": 0,
"def": 2000,
"level": 3,
"race": "Dragon",
"attribute": "WATER",
"archetype": null
},
{
"id": 35261759,
"name": "Pot of Desires",
"type": "2 Spell Cards",
"desc": "Banish 10 cards from the top of your Deck, face-down; draw 2 cards. You can only activate 1 \"Pot of Desires\" per turn.",
"atk": null,
"def": null,
"level": null,
"race": "Normal",
"attribute": null,
"archetype": "Greed"
},
{
"id": 22862454,
"name": "Proxy Dragon",
"type": "1 Link Monster",
"desc": "2 monsters\r\nIf a card(s) you control would be destroyed by battle or card effect, you can destroy 1 of your monsters this card points to, instead.",
"atk": 1400,
"def": null,
"level": null,
"race": "Cyberse",
"attribute": "LIGHT",
"archetype": null
}
]
}
}
CONFIG:
{}
Upvotes: 0
Reputation: 48889
I don't think this is possible, see https://github.com/vega/vega-tooltip/issues/251. In summary it seems like Vega and VegaTooltip does remove fields with Undefined
form the tooltip, but VegaLite forces these to be shown in the tooltip (compare this VegaLite spec with this Vega one). It seems like they are looking for help to implement the feature you want.
Here is an example with your data that illustrates how both null
and Undefined
values show up in the tooltip:
df = pd.DataFrame([{
"id":89631139,
"name":"Blue-Eyes White Dragon",
"type":"Normal Monster",
"atk":3000,
"def":2500,
"level":8,
"race":"Dragon",
"attribute":"LIGHT",
"archetype":"Blue-Eyes"
},
{
"id":35261759,
"name":"Pot of Desires",
"type":"Spell Card",
"race":"Normal",
"archetype":"Greed"
}])
alt.Chart(df).mark_point(tooltip={'content': 'data'}).encode(
x='name',
y='type'
).transform_calculate(
A = "isValid(datum.atk) ? datum.atk : 'Undefined'",
D = "isValid(datum.def) ? datum.def : 'Undefined'"
)
Upvotes: 1