英文:
vega-lite deneb grouped bar chart - Labels positioning
问题
我仍在优化这个项目:
(以上链接中的解决方案代码已贴在底部+图像)。
我想在此可视化中添加显示项目日期的数据标签,但取决于“Country slicer”和以下条件,我想动态调整“dx”。是否可能?
我的条件
1 - 如果_Date_Target 大于或小于 _Date_Today(显示柱状图点左或右)
2 - 是否选择“Country slicer”(如果选择了,则x轴的刻度与所有国家都可见时不同)
3 - _Date_Target 和 _Date_Today 之间的天数(确定柱状条的长度)
需要这样做的原因是在某些组合中,例如今天和目标之间的差异很小时,我的标签可能不可见或位置不正确。
因此,基本设计是在柱状条的末端内部显示它们。
但如果目标接近,则在柱状条外部显示。
例如:
如果 _date_target 大于今天,并且选择了切片器,并且目标和今天之间的差异小于 200 天,那么我希望 dx 的值为 A1
否则
如果 _date_target 大于今天,并且选择了切片器,并且目标和今天之间的差异大于等于 200 天,那么我希望 dx 的值为 A2
否则
如果 _date_target 大于今天,并且切片器未选择,并且目标和今天之间的差异小于 50,则 dx 的值为 B1
否则
如果 _date_target 大于今天,并且切片器未选择,并且目标和今天之间的差异大于等于 50,则 dx 的值为 B2
以上逻辑仅适用于指向右侧的柱状图(未来的目标)
然后,我需要类似的逻辑来指向左侧的柱状图。
**是否有更简单的方法来实现这个结果?**也许可以比较柱状标记的长度和文本标记的长度?如果差异太大,则调整位置?
前一问题的代码和图像:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {
"values": [
{
"name": "A",
"country": "BBB",
"_Date_Target": "2023-02-20",
"_Date_Today": "2023-05-03"
},
{
"name": "A1",
"country": "AAA",
"_Date_Target": "2023-01-10",
"_Date_Today": "2023-05-03"
},
{
"name": "B",
"country": "BBB",
"_Date_Target": "2023-08-21",
"_Date_Today": "2023-05-03"
},
{
"name": "E",
"country": "AAA",
"_Date_Target": "2023-09-01",
"_Date_Today": "2023-05-03"
},
{
"name": "F",
"country": "AAA",
"_Date_Target": "2023-08-15",
"_Date_Today": "2023-05-03"
},
{
"name": "G",
"country": "AAA",
"_Date_Target": "2023-11-20",
"_Date_Today": "2023-05-03"
}
]
},
"spacing": -8,
"facet": {
"row": {
"field": "country",
"type": "ordinal",
"header": {"title": null, "labelAngle": 0}
}
},
"spec": {
"height": {"step": 25},
"layer": [
{
"mark": {"type": "bar", "tooltip": true},
"encoding": {
"y": {
"field": "name",
"type": "nominal",
"axis": {"title": null, "grid": false, "tickBand": "extent"}
},
"x": {
"field": "_Date_Today",
"type": "temporal",
"axis": {
"title": null,
"format": "%b-%y",
"grid": true,
"gridWidth": 1,
"gridColor": "grey",
"gridDash": [4, 4],
"gridOpacity": {
"condition": {
"test": {"field": "value", "timeUnit": "month", "equal": 1},
"value": 0.5
},
"value": 0
}
}
},
"x2": {"field": "_Date_Target"}
}
},
{
"mark": {"type": "rule", "color": "red"},
"encoding": {"x": {"field": "_Date_Today", "type": "temporal"}}
}
]
},
"resolve": {"scale": {"y": "independent"}},
"config": {"view": {"stroke": "silver"}}
}
我尝试过使用度量值,"dx" + "condition" + "and","condition" 与数组 [],还有 "expr" 的变体。文本的颜色已根据条件进行了条件格式化,如果差异太大,则为黑白色调(在 "condition" 内使用度量值)。
英文:
i am still polishing this project:
https://stackoverflow.com/questions/76170255/vega-lite-deneb-grouped-bar-chart/76170781#76170781
(The solution code from above link is pasted at the bottom + image).
I would like to add data labels to this visual showing project date but depending on Country slicer and conditions below i would like to dynamically adjust "dx". **Is it possible? **
My conditions
1 - if _Date_Target is > or < than _Date_Today (shows if bar point left or right)
2 - Country slicer is selected or not (if selected then scale of x-axis is different than if all countries are visible)
3 - Number of days between _Date_Target and _Date_Today (determines the lenght of the bar)
The need is coming from the fact that in some combinations e.g small difference between today and target my labels are not visible or position is not correct.
So the basic design is to show them inside of the bar at its end.
But if the target is close then outside of the bar.
So for example:
if _date_target > today and slicer is selected and difference between target and today is < 200 days then i would like dx with value A1
else
if _date_target > today and slicer is selected and difference between target and today is >= 200 days then i would like dx with value A2
else
if _date_target > today and slicer is NOT selected and difference between target and today is <50 then dx with value B1
else
if _date_target > today and slicer is NOT selected and difference between target and today is >=50 then dx with value B2
So the above logic is only for bars pointing right (target in the future)
Then again i would need similar logic for bars pointing left.
Is there a simpler method to achieve the result? Maybe it is posible to compare length of bar mark with length of text mark? and if difference is too big than positioning is adjusted?
Code and image from the previous question:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {
"values": [
{
"name": "A",
"country": "BBB",
"_Date_Target": "2023-02-20",
"_Date_Today": "2023-05-03"
},
{
"name": "A1",
"country": "AAA",
"_Date_Target": "2023-01-10",
"_Date_Today": "2023-05-03"
},
{
"name": "B",
"country": "BBB",
"_Date_Target": "2023-08-21",
"_Date_Today": "2023-05-03"
},
{
"name": "E",
"country": "AAA",
"_Date_Target": "2023-09-01",
"_Date_Today": "2023-05-03"
},
{
"name": "F",
"country": "AAA",
"_Date_Target": "2023-08-15",
"_Date_Today": "2023-05-03"
},
{
"name": "G",
"country": "AAA",
"_Date_Target": "2023-11-20",
"_Date_Today": "2023-05-03"
}
]
},
"spacing": -8,
"facet": {
"row": {
"field": "country",
"type": "ordinal",
"header": {"title": null, "labelAngle": 0}
}
},
"spec": {
"height": {"step": 25},
"layer": [
{
"mark": {"type": "bar", "tooltip": true},
"encoding": {
"y": {
"field": "name",
"type": "nominal",
"axis": {"title": null, "grid": false, "tickBand": "extent"}
},
"x": {
"field": "_Date_Today",
"type": "temporal",
"axis": {
"title": null,
"format": "%b-%y",
"grid": true,
"gridWidth": 1,
"gridColor": "grey",
"gridDash": [4, 4],
"gridOpacity": {
"condition": {
"test": {"field": "value", "timeUnit": "month", "equal": 1},
"value": 0.5
},
"value": 0
}
}
},
"x2": {"field": "_Date_Target"}
}
},
{
"mark": {"type": "rule", "color": "red"},
"encoding": {"x": {"field": "_Date_Today", "type": "temporal"}}
}
]
},
"resolve": {"scale": {"y": "independent"}},
"config": {"view": {"stroke": "silver"}}
}
I've tried using measures for that, "dx" + "condition" + "and", "condition" with array [], also variations of "expr". Color of text is already conditionally formatted to black and white depending on conditions (using a measure inside "condition").
答案1
得分: 0
我已经修改了代码,使目标日期出现在每个柱形内部。如果您希望目标日期出现在柱形外部,您可以在表达式中添加一些额外的逻辑。
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {
"values": [
{
"name": "A",
"country": "BBB",
"_Date_Target": "2023-01-20",
"_Date_Today": "2023-05-03",
"name_focus": "Y"
},
{
"name": "A1",
"country": "AAA",
"_Date_Target": "2023-01-10",
"_Date_Today": "2023-05-03",
"name_focus": "Y"
},
{
"name": "B",
"country": "BBB",
"_Date_Target": "2023-08-21",
"_Date_Today": "2023-05-03",
"name_focus": "N"
},
{
"name": "E",
"country": "AAA",
"_Date_Target": "2023-09-01",
"_Date_Today": "2023-05-03",
"name_focus": "N"
},
{
"name": "F",
"country": "AAA",
"_Date_Target": "2023-08-15",
"_Date_Today": "2023-05-03",
"name_focus": "N"
},
{
"name": "G",
"country": "AAA",
"_Date_Target": "2023-11-20",
"_Date_Today": "2023-05-03",
"name_focus": "N"
}
]
},
"transform": [
{"calculate": "datum.name + ' | ' + datum.name_focus", "as": "name_full"},
{
"calculate": "(datetime(datum._Date_Target)-datetime(datum._Date_Today)) / (24*60*60*1000)",
"as": "days_difference"
}
],
"spacing": -10,
"facet": {
"row": {
"field": "country",
"type": "ordinal",
"header": {"title": null, "labelAngle": 0}
}
},
"spec": {
"height": {"step": 25},
"layer": [
{
"mark": {"type": "bar", "tooltip": true},
"encoding": {
"y": {
"field": "name_full",
"type": "nominal",
"axis": {
"title": null,
"grid": false,
"tickBand": "extent",
"labelExpr": "split(datum.label, ' | ')[0]",
"labelFontWeight": {
"expr": "indexof(datum.label, '|Y') !== -1 ? 'bold' : 'normal'"
},
"labelColor": {
"expr": "indexof(datum.label, '|Y') !== -1 ? '#4c78a8' : 'gray'"
},
"labelFontSize": {
"expr": "indexof(datum.label, '|Y') !== -1 ? '12' : '10'"
},
"labelPadding": {
"expr": "indexof(datum.label, '|Y') !== -1 ? '5' : '0'"
}
}
},
"x": {
"field": "_Date_Today",
"type": "temporal",
"axis": {
"title": null,
"format": "%b-%y",
"grid": true,
"gridWidth": 1,
"gridColor": "grey",
"gridDash": [4, 4],
"gridOpacity": {
"condition": {
"test": {"field": "value", "timeUnit": "month", "equal": 1},
"value": 0.5
},
"value": 0
}
}
},
"x2": {"field": "_Date_Target"}
}
},
{
"mark": {"type": "rule", "color": "red"},
"encoding": {"x": {"field": "_Date_Today", "type": "temporal"}}
},
{
"mark": {
"type": "text",
"align": "right",
"baseline": "middle",
"dx": {
"expr": "datum.days_difference > 0 ? 15 : (datum.days_difference < 0 ? -35 : 0)"
},
"color": {"expr": "datum.days_difference > 100 ? 'white' : 'orange'"}
},
"encoding": {
"y": {"field": "name_full", "type": "nominal"},
"text": {
"field": "_Date_Target",
"type": "temporal",
"format": "%d-%b"
}
}
}
]
},
"resolve": {"scale": {"y": "independent"}},
"config": {
"view": {"stroke": "silver"},
"style": {"cell": {"stroke": "transparent"}}
}
}
英文:
I have modified the code so that the target dates appear inside each bar. You can add some extra logic on the expression if you want the target date to appear outside the bars.
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {
"values": [
{
"name": "A",
"country": "BBB",
"_Date_Target": "2023-01-20",
"_Date_Today": "2023-05-03",
"name_focus": "Y"
},
{
"name": "A1",
"country": "AAA",
"_Date_Target": "2023-01-10",
"_Date_Today": "2023-05-03",
"name_focus": "Y"
},
{
"name": "B",
"country": "BBB",
"_Date_Target": "2023-08-21",
"_Date_Today": "2023-05-03",
"name_focus": "N"
},
{
"name": "E",
"country": "AAA",
"_Date_Target": "2023-09-01",
"_Date_Today": "2023-05-03",
"name_focus": "N"
},
{
"name": "F",
"country": "AAA",
"_Date_Target": "2023-08-15",
"_Date_Today": "2023-05-03",
"name_focus": "N"
},
{
"name": "G",
"country": "AAA",
"_Date_Target": "2023-11-20",
"_Date_Today": "2023-05-03",
"name_focus": "N"
}
]
},
"transform": [
{"calculate": "datum.name + '|' + datum.name_focus", "as": "name_full"},
{
"calculate": "(datetime(datum._Date_Target)-datetime(datum._Date_Today)) / (24*60*60*1000)",
"as": "days_difference"
}
],
"spacing": -10,
"facet": {
"row": {
"field": "country",
"type": "ordinal",
"header": {"title": null, "labelAngle": 0}
}
},
"spec": {
"height": {"step": 25},
"layer": [
{
"mark": {"type": "bar", "tooltip": true},
"encoding": {
"y": {
"field": "name_full",
"type": "nominal",
"axis": {
"title": null,
"grid": false,
"tickBand": "extent",
"labelExpr": "split(datum.label, '|')[0]",
"labelFontWeight": {
"expr": "indexof(datum.label, '|Y') !== -1 ?'bold':'normal'"
},
"labelColor": {
"expr": "indexof(datum.label, '|Y') !== -1 ? '#4c78a8':'gray'"
},
"labelFontSize": {
"expr": "indexof(datum.label, '|Y') !== -1 ? '12':'10'"
},
"labelPadding": {
"expr": "indexof(datum.label, '|Y') !== -1 ? '5':'0'"
}
}
},
"x": {
"field": "_Date_Today",
"type": "temporal",
"axis": {
"title": null,
"format": "%b-%y",
"grid": true,
"gridWidth": 1,
"gridColor": "grey",
"gridDash": [4, 4],
"gridOpacity": {
"condition": {
"test": {"field": "value", "timeUnit": "month", "equal": 1},
"value": 0.5
},
"value": 0
}
}
},
"x2": {"field": "_Date_Target"}
}
},
{
"mark": {"type": "rule", "color": "red"},
"encoding": {"x": {"field": "_Date_Today", "type": "temporal"}}
},
{
"mark": {
"type": "text",
"align": "right",
"baseline": "middle",
"dx": {
"expr": "datum.days_difference > 0 ? 15 : (datum.days_difference < 0 ? -35 : 0)"
},
"color": {"expr": "datum.days_difference > 100 ? 'white' : 'orange'"}
},
"encoding": {
"y": {"field": "name_full", "type": "nominal"},
"text": {
"field": "_Date_Target",
"type": "temporal",
"format": "%d-%b"
}
}
}
]
},
"resolve": {"scale": {"y": "independent"}},
"config": {
"view": {"stroke": "silver"},
"style": {"cell": {"stroke": "transparent"}}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论