Related
I am using this Stacked Bar Chart Example at the link: https://vega.github.io/vega/examples/stacked-bar-chart/
But I can't figure out how to show the field title on axis x and y.
I want to show the title x and y below.
Is there a way to display the label title on the x and y axes?
Just add a title attribute.
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "A basic stacked bar chart example.",
"width": 500,
"height": 200,
"padding": 5,
"data": [
{
"name": "table",
"values": [
{"x": 0, "y": 28, "c": 0}, {"x": 0, "y": 55, "c": 1},
{"x": 1, "y": 43, "c": 0}, {"x": 1, "y": 91, "c": 1},
{"x": 2, "y": 81, "c": 0}, {"x": 2, "y": 53, "c": 1},
{"x": 3, "y": 19, "c": 0}, {"x": 3, "y": 87, "c": 1},
{"x": 4, "y": 52, "c": 0}, {"x": 4, "y": 48, "c": 1},
{"x": 5, "y": 24, "c": 0}, {"x": 5, "y": 49, "c": 1},
{"x": 6, "y": 87, "c": 0}, {"x": 6, "y": 66, "c": 1},
{"x": 7, "y": 17, "c": 0}, {"x": 7, "y": 27, "c": 1},
{"x": 8, "y": 68, "c": 0}, {"x": 8, "y": 16, "c": 1},
{"x": 9, "y": 49, "c": 0}, {"x": 9, "y": 15, "c": 1}
],
"transform": [
{
"type": "stack",
"groupby": ["x"],
"sort": {"field": "c"},
"field": "y"
}
]
}
],
"scales": [
{
"name": "x",
"type": "band",
"range": "width",
"domain": {"data": "table", "field": "x"}
},
{
"name": "y",
"type": "linear",
"range": "height",
"nice": true, "zero": true,
"domain": {"data": "table", "field": "y1"}
},
{
"name": "color",
"type": "ordinal",
"range": "category",
"domain": {"data": "table", "field": "c"}
}
],
"axes": [
{"orient": "bottom", "scale": "x", "zindex": 1, "title":"x"},
{"orient": "left", "scale": "y", "zindex": 1, "title":"y"}
],
"marks": [
{
"type": "rect",
"from": {"data": "table"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "x"},
"width": {"scale": "x", "band": 1, "offset": -1},
"y": {"scale": "y", "field": "y0"},
"y2": {"scale": "y", "field": "y1"},
"fill": {"scale": "color", "field": "c"}
},
"update": {
"fillOpacity": {"value": 1}
},
"hover": {
"fillOpacity": {"value": 0.5}
}
}
}
]
}
How can I flatten "Behavior" field so it becomes part of the document root ? I have tried with $project and $unwind functions but that ones did not seem to help me
I have json data like this:
"breed": "Akita",
"origin": "Japan",
"url": "https://en.wikipedia.org/wiki/Akita_(dog)",
"img": "some img url",
"WikiDescr": [
{
"contenido": "Content"
}
],
"Behavior": [
{
"good_with_children": 3,
"good_with_other_dogs": 1,
"shedding": 3,
"grooming": 3,
"drooling": 1,
"coat_length": 1,
"good_with_strangers": 2,
"playfulness": 3,
"protectiveness": 5,
"trainability": 3,
"energy": 4,
"barking": 2,
"min_life_expectancy": 10,
"max_life_expectancy": 14,
"max_height_male": 28,
"max_height_female": 28,
"max_weight_male": 130,
"max_weight_female": 100,
"min_height_male": 26,
"min_height_female": 26,
"min_weight_male": 100,
"min_weight_female": 70
}
and my desired output would be like this:
"breed": "Akita",
"origin": "Japan",
"url": "https://en.wikipedia.org/wiki/Akita_(dog)",
"img": "some img url",
"good_with_children": 3,
"good_with_other_dogs": 1,
"shedding": 3,
"grooming": 3,
"drooling": 1,
"coat_length": 1,
"good_with_strangers": 2,
"playfulness": 3,
"protectiveness": 5,
"trainability": 3,
"energy": 4,
"barking": 2,
"min_life_expectancy": 10,
"max_life_expectancy": 14,
"max_height_male": 28,
"max_height_female": 28,
"max_weight_male": 130,
"max_weight_female": 100,
"min_height_male": 26,
"min_height_female": 26,
"min_weight_male": 100,
"min_weight_female": 70
},
"WikiDescr": [
{
"contenido": "content"
}
],
I have tried this but it does not happen anything:
{ $unwind: "$Behavior" },
{ $replaceRoot: { newRoot: { $mergeObjects: ["$Behavior", "$$ROOT"] } } },
Any help would be appreciated since I am stuck with this trivial question
Underneath this you can see my code. I commented the line which causes the error. Error message: "No exact matches in call to subscript". Do you know how I can avoid this error? Thank you for your help!
let dic = ["a": 1, "b": 2, "c": 3, "d": 4, "e": 5, "f": 6, "g": 7, "h": 8, "i": 9, "j": 10, "k": 11, "l": 12, "m": 13, "n": 14, "o": 15, "p": 16, "q": 17, "r": 18, "s": 19, "t": 20, "u": 21, "v": 22, "w": 23, "x": 24, "y": 25, "z": 26]
var newwrd = ""
for var i in str ?? "" {
let ci = dic[i] // This line causes the error
}
Actually you should get the error
Cannot subscript a value of type '[String : Int]' with an argument of type 'String.Element' (aka 'Character')
str is obviously String?, the element type when enumerating a string is Character but the subscription type must be String.
let dic = ["a": 1, "b": 2, "c": 3, "d": 4, "e": 5, "f": 6, "g": 7, "h": 8, "i": 9, "j": 10, "k": 11, "l": 12, "m": 13, "n": 14, "o": 15, "p": 16, "q": 17, "r": 18, "s": 19, "t": 20, "u": 21, "v": 22, "w": 23, "x": 24, "y": 25, "z": 26]
for i in str ?? "" { // no need for var i
let ci = dic[String(i)] ?? 0
print(ci)
}
If the string contains a character which is not in the dictionary the result is 0.
There is a shorter way without a helper dictionary
for i in str ?? "" where ("a"..."z") ~= i {
let ci = Int(i.asciiValue!) - 96
print(ci)
}
As #vadian says, it looks like str is an Optional<String>. Looping through a string gives you Characters, but your dictionary keys are Strings. You need to convert each character to a String, and deal with optionals. Try this code:
let str: String? = "abcqrml#"
let dic = ["a": 1, "b": 2, "c": 3, "d": 4, "e": 5, "f": 6, "g": 7, "h": 8, "i": 9, "j": 10, "k": 11, "l": 12, "m": 13, "n": 14, "o": 15, "p": 16, "q": 17, "r": 18, "s": 19, "t": 20, "u": 21, "v": 22, "w": 23, "x": 24, "y": 25, "z": 26]
var newwrd = ""
for i in str ?? "" {
if let ci = dic[String(i)] {
print("dic[\(i)] = \(ci)")
} else {
print("dic[\(i)] = nil")
}
}
I am storing the assessments of students in a jsonb column call assessment, every row in the database stores the assessments of students for a particular subject, and i am trying to get a query that will help retrieve:
1. A student assessment for a particular subject.
2. All the student assessments for every subject offer by the student.
Here is a same of the result i get when i select all records from the table.
[
{
"id": "22670f29-1437-4af1-b907-f6940377a851",
"sessionId": 3,
"sectionId": 4,
"subjectId": 8,
"assessment": [
{
"exam": 50,
"grdae": "A",
"total": 79,
"position": "First",
"student_id": 2,
"assessment_1": 9,
"assessment_2": 17,
"assessment_4": 5,
"student_name": "Anana Aristotle"
},
{
"exam": 50,
"grdae": "B",
"total": 69,
"position": "Third",
"student_id": 3,
"assessment_1": 9,
"assessment_2": 17,
"assessment_4": 5,
"student_name": "Anana Elvis"
}
]
},
{
"id": "beca9d97-0d0a-4d89-b8c5-c9a6fed812a5",
"sessionId": 3,
"sectionId": 4,
"subjectId": 10,
"assessment": [
{
"exam": 50,
"grdae": "A",
"total": 79,
"position": "First",
"student_id": 2,
"assessment_1": 9,
"assessment_2": 17,
"assessment_4": 5,
"student_name": "Anana Aristotle"
},
{
"exam": 50,
"grdae": "B",
"total": 69,
"position": "Third",
"student_id": 3,
"assessment_1": 9,
"assessment_2": 17,
"assessment_4": 5,
"student_name": "Anana Elvis"
}
]
},
{
"id": "1ed9c3d6-2482-4b1d-ab59-b77a8933699c",
"sessionId": 3,
"sectionId": 4,
"subjectId": 9,
"assessment": [
{
"exam": 50,
"grdae": "A",
"total": 90,
"position": "First",
"student_id": 2,
"assessment_1": 9,
"assessment_2": 17,
"assessment_4": 5,
"student_name": "Anana Aristotle"
},
{
"exam": 50,
"grdae": "B",
"total": 69,
"position": "Third",
"student_id": 3,
"assessment_1": 9,
"assessment_2": 17,
"assessment_4": 5,
"student_name": "Anana Elvis"
}
]
}
]
This result contains assessment for the different subjects, with subjectIds, 8, 9 ,and 10 for two students with ids 2 and 3.
NOTE: sessionID,SectionID and subjectId are also columns in the table call assessment.
I should be able to get this object in return if i want a student with id 2 assessment for a subjectId of 9 and sessionId is 3 and also sectionId is 4:
{
"exam": 50,
"grdae": "A",
"total": 90,
"position": "First",
"student_id": 2,
"assessment_1": 9,
"assessment_2": 17,
"assessment_4": 5,
"student_name": "Anana Aristotle"
}
And i should be a to get this result, if i want a student with id 2 assessment for all three subjectIds, i.e id 8, 9, 10, and sessionId is 3 and also sectionId is 4:
[
{
"exam": 50,
"grdae": "A",
"total": 90,
"position": "First",
"student_id": 2,
"assessment_1": 9,
"assessment_2": 17,
"assessment_4": 5,
"student_name": "Anana Aristotle"
},
{
"exam": 50,
"grdae": "A",
"total": 79,
"position": "First",
"student_id": 2,
"assessment_1": 9,
"assessment_2": 17,
"assessment_4": 5,
"student_name": "Anana Aristotle"
},
{
"exam": 50,
"grdae": "A",
"total": 79,
"position": "First",
"student_id": 2,
"assessment_1": 9,
"assessment_2": 17,
"assessment_4": 5,
"student_name": "Anana Aristotle"
}
]
Minimized your data in the fiddle to:
[
{
"sessionId": 3,
"sectionId": 4,
"subjectId": 8,
"assessment": [
{
"student_id": 2
},
{
"student_id": 3
}
]
},
{
"sessionId": 3,
"sectionId": 4,
"subjectId": 10,
"assessment": [
{
"student_id": 2
},
{
"student_id": 3
}
]
},
{
"sessionId": 3,
"sectionId": 4,
"subjectId": 9,
"assessment": [
{
"student_id": 2
},
{
"student_id": 3
}
]
}
]
demo:db<>fiddle
The first step is to unnest the relevant id information:
SELECT
assessments,
(elems ->> 'sessionId')::int as session_id,
(elems ->> 'sectionId')::int as section_id,
(elems ->> 'subjectId')::int as subject_id,
(assessments ->> 'student_id')::int AS student_id
FROM
mytable,
json_array_elements(jsondata) as elems,
json_array_elements(elems -> 'assessment') as assessments
This results in:
assessments | session_id | section_id | subject_id | student_id
:--------------- | ---------: | ---------: | ---------: | ---------:
{"student_id":2} | 3 | 4 | 8 | 2
{"student_id":3} | 3 | 4 | 8 | 3
{"student_id":2} | 3 | 4 | 10 | 2
{"student_id":3} | 3 | 4 | 10 | 3
{"student_id":2} | 3 | 4 | 9 | 2
{"student_id":3} | 3 | 4 | 9 | 3
The json_array_elements() function unnest the json array into one record per array element. Because there are two nested arrays, you need to call this function twice. You can get the values of each level as you can see within the SELECT list.
After that you are able to filter whatever you want within the WHERE clause. The resulting records (the relevant assessment objects) can be grouped with json_agg() aggregate function:
SELECT
json_agg(assessments)
FROM (
-- query from above
) s
WHERE session_id IN (3)
AND section_id IN (4)
AND subject_id IN (9) -- only one subject
AND student_id IN (2)
or
SELECT
json_agg(assessments)
FROM (
-- query from above
) s
WHERE session_id IN (3)
AND section_id IN (4)
AND subject_id IN (8,9,10) -- more subjects
AND student_id IN (2)
A PostgreSQL 10 table contains JSON data like (here an SQL Fiddle):
[
{
"col": 7,
"row": 12,
"value": 3,
"letter": "A"
},
{
"col": 8,
"row": 12,
"value": 10,
"letter": "B"
},
{
"col": 9,
"row": 12,
"value": 1,
"letter": "C"
},
{
"col": 10,
"row": 12,
"value": 2,
"letter": "D"
}
]
How to extract only the "letter" values and concatenate them to a string like
ABCD
I suppose at the end I should use the ARRAY_TO_STRING function, but which JSON function to use for extracting the "letter" values to an array?
UPDATE:
Got a tip at the very helpful PostgreSQL mailing list too:
SELECT string_agg(x->>'letter','') FROM json_array_elements(
'[{"col": 7, "row": 12, "value": 3, "letter": "A"}, {"col": 8, "row": 12, "value": 10, "letter": "B"}, {"col": 9, "row": 12, "value": 1, "letter": "C"}, {"col": 10, "row": 12, "value": 2, "letter": "D"}]'::json
) x;
Use jsonb_array_elements() and string_agg():
with my_table(json_data) as (
values(
'[
{
"col": 7,
"row": 12,
"value": 3,
"letter": "A"
},
{
"col": 8,
"row": 12,
"value": 10,
"letter": "B"
},
{
"col": 9,
"row": 12,
"value": 1,
"letter": "C"
},
{
"col": 10,
"row": 12,
"value": 2,
"letter": "D"
}
]'::jsonb)
)
select string_agg(value->>'letter', '')
from my_table
cross join lateral jsonb_array_elements(json_data)
string_agg
------------
ABCD
(1 row)