I need to convert a dataframe to JSON. There are several nested dataframes as variables in the dataframe to convert to JSON.
But, when converting to JSON, I need the data for Values1 described below to be an object (enclosed in {} only) instead of an array (enclosed in []).
The code below is a reprex to show my current workflow and problem.
library(dplyr)
library(tidyr)
library(jsonlite)
df1 <- data.frame(name = c("a", "b", "c"),
v = c(1, 2, 3),
w = c(10, 20, 30)) %>%
group_by(name) %>%
nest_legacy(.key = "Values1")
df2 <- data.frame(name = c("a", "b", "c"),
x = c(5, 10, 15),
y = c(100, 200, 300),
z = c(1000, 2000, 3000)) %>%
group_by(name) %>%
nest_legacy(.key = "Values2")
df3 <- df1 %>%
left_join(df2)
json <- toJSON(df3, dataframe = "rows", pretty = TRUE)
json
This is what the json from the above looks like:
> json
[
{
"name": "a",
"Values1": [
{
"v": 1,
"w": 10
}
],
"Values2": [
{
"x": 5,
"y": 100,
"z": 1000
}
]
},
{
"name": "b",
"Values1": [
{
"v": 2,
"w": 20
}
],
"Values2": [
{
"x": 10,
"y": 200,
"z": 2000
}
]
},
{
"name": "c",
"Values1": [
{
"v": 3,
"w": 30
}
],
"Values2": [
{
"x": 15,
"y": 300,
"z": 3000
}
]
}
]
But, this is what I need it to look like:
> json
[
{
"name": "a",
"Values1": {
"v": 1,
"w": 10
},
"Values2": [
{
"x": 5,
"y": 100,
"z": 1000
}
]
},
{
"name": "b",
"Values1": {
"v": 2,
"w": 20
},
"Values2": [
{
"x": 10,
"y": 200,
"z": 2000
}
]
},
{
"name": "c",
"Values1": {
"v": 3,
"w": 30
},
"Values2": [
{
"x": 15,
"y": 300,
"z": 3000
}
]
}
]
Any ideas how to convert Values1 from arrays to objects? They cannot be in arrays as the API does not accept the [.
I have looked at using unbox() from jsonlite but this only works on singletons. I have also tried to construct my final dataframe in various ways.
Any tips/ideas greatly appreciated!
This should return what you desire:
...
df3 <- left_join(df1, df2, by = "name")
json <- mutate(df3, Values1 = purrr::map(Values1, as.list)) %>%
jsonlite::toJSON(auto_unbox = TRUE, pretty = TRUE)
Can you confirm?
Related
Need help with converting this df to exact JSON as an example using R. Already tried a lot of approaches but cant succeed. Please help.
Code for generating sample:
df <- data.frame(month = c(1, 1, 1, 2, 2, 2),
station = c('AE', 'DС', 'CL', 'AE', 'DC', 'CL'),
persons = c(3, 12, 21, 12, 10, 9),
results = c(10, 34, 57, 19, 16, 5)
)
Its needed to drop column "station" and add level "summary" which gather results to pairs "person" and "results" just as like example shows.
Needed JSON output.
[
{
"month": "1",
"summary": [
{
"persons": 3,
"results": 10
},
{
"persons": 12,
"results": 34
},
{
"persons": 21,
"results": 57
}
]
},
{
"month": "2",
"summary": [
{
"persons": 12,
"results": 19
},
{
"persons": 10,
"results": 16
},
{
"persons": 9,
"results": 5
}
]
}
]
You could use tidyr::nest and jsonlite::toJson like so:
library(tidyr)
library(dplyr)
library(jsonslite)
df |>
select(-station) |>
group_by(month) |>
nest() |>
rename(summary = data) |>
jsonlite::toJSON()
#> [{"month":1,"summary":[{"persons":3,"results":10},{"persons":12,"results":34},{"persons":21,"results":57}]},{"month":2,"summary":[{"persons":12,"results":19},{"persons":10,"results":16},{"persons":9,"results":5}]}]
I'm trying to align axis labels in HighCharts
Labels should not be trimed, so ellipsis is not allowed
How it looks now:
How I want it to be:
Code: https://jsfiddle.net/9xw6dL3f/25/
{
"chart": {
"width": 500,
"height": 300,
"type": "column"
},
"title": {
"text": null
},
"xAxis": {
"type": "category",
"labels": {
"rotation": -90,
"style": {
"textOverflow": "none"
}
}
},
"series": [
{
"name": "",
"data": [
{ "name": "Follow me into my theatre of lunacy", "y": -10, "color": "#ABC" },
{ "name": "1", "y": 1, "color": "#000" },
{ "name": "2", "y": 2, "color": "#000" },
{ "name": "3", "y": 3, "color": "#000" },
{ "name": "4", "y": 4, "color": "#000" },
{ "name": "5", "y": 5, "color": "#000" },
]
}
]
}
It is possible to move label depending on it's rows count
Add render function to the chart object
{
"chart": {
...
events: {
render() {
for (let i = 0; i < this.xAxis[0].names.length; i++) {
const label = this.xAxis[0].ticks[i].label;
const rows = (label.element.innerHTML.match(/<\/tspan>/g) || []).length;
label.translate(-8 * rows, 0);
}
}
}
where 8 is half of row size in px
https://jsfiddle.net/kLz1uoga/5/
I have data in JSON format like this in my elasticsearch:
{
"features": [
{
"feature": "A",
"Yes": 19,
"No": 0,
"Maybe": 81
},
{
"feature": "B",
"Yes": 0,
"No": 0,
"Maybe": 100
},
{
"feature": "C",
"Yes": 10,
"No": 32,
"Maybe": 58
}
]
}
From this, is it possible to obtain a stacked chart as follows?
I need to add labels with difference of 10 in both axis( one each between the grid ), WITHOUT compromising the present number of grids.So the number of grid lines should stay 11 and number of labels will go up to 21. Hope that clears my query.Above is my chart, and this is the code -
var chart = AmCharts.makeChart("chartdiv", {
"type": "xy",
"dataProvider": json,
"valueAxes":
[
{
"id":"my_y",
"autoGridCount": false,
"position": "right",
"tickLength":0,
"gridThickness":0.25,
"minimum":-100,
"maximum":100,
"gridCount": 11,
"labelFrequency" : 0.5,
"gridColor":"black",
"gridAlpha":0.50,
"labelOffset": -356,
"axisAlpha":0,
"strictGridCount" : true,
},
{
"id":"my_x",
"autoGridCount": false,
"position": "bottom",
"tickLength":0,
"gridThickness": 0.25,
"minimum":-100,
"maximum":100,
"gridCount": 11,
"labelFrequency" : 0.5,
"gridColor":"black",
"gridAlpha":0.50,
"labelOffset": -320,
"axisAlpha":0,
},
],
"borderAlpha" : 0,
"startDuration": 0,
"legend":[{
"useGraphSettings": false,
"verticalGap":0,
}],
"guides":[
{
"fillAlpha": 0.10,
"value": -100,
"toValue": 100,
}
],
"graphs":
[
{
"id":"g1",
"lineColor": "#FF6600",
"bulletBorderThickness": 1,
"hideBulletsCount": 30,
"animationDuration":0,
"balloonText": "[[value]]",
"bullet": "circle",
"lineAlpha": 0,
"valueField": "value",
"xField": "x",
"yField": "y",
"fillAlphas": 0,
"bulletBorderAlpha": 0,
"minBulletSize": 30,
"maxBulletSize": 30,
"labelText":"[[x]]",
"labelPosition":"inside",
"markerType" : "none",
"switchable":false,
},
],
"marginLeft": 20,
"marginBottom": 20,
"export": {
"enabled": true,
"menu" : [],
},
});
PS : I tried to change the labelFrequency value but I don't think it takes values below 1.
You're right to assume that labelFrequency can't be set to anything lower than 1, or a non-integer for that matter.
The only workaround I can think of is to increase gridCount to the number which displays labels in increments that you want. I.e. 21.
Then disable grid lines altogether. (gridAlpha: 0)
And finally use guides to display lines at values that you need lines displayed at. I.e.:
{
"id": "my_y",
"autoGridCount": false,
"position": "right",
"tickLength": 0,
"gridThickness": 0.25,
"minimum": -100,
"maximum": 100,
"gridCount": 21,
"labelFrequency": 0.5,
"gridColor": "black",
"gridAlpha": 0,
"labelOffset": -356,
"axisAlpha": 0,
"strictGridCount": true,
"guides": [
{ "value": 80, "lineAlpha": 0.5 },
{ "value": 60, "lineAlpha": 0.5 },
{ "value": 40, "lineAlpha": 0.5 },
{ "value": 20, "lineAlpha": 0.5 },
{ "value": 0, "lineAlpha": 0.5 },
{ "value": -20, "lineAlpha": 0.5 },
{ "value": -40, "lineAlpha": 0.5 },
{ "value": -60, "lineAlpha": 0.5 },
{ "value": -80, "lineAlpha": 0.5 }
]
}
I've a JSON object as follows which is most of the time having no specific structures. This been created from the client side using jquery and sending to the server side via AJAX.
{
"items": {
"1": [{
"text": "Man",
"itemID": "1",
"checked": 1,
"sequence": 1,
"matchingtext": "",
"weight": 0
}, {
"text": "goat",
"itemID": "2",
"checked": 0,
"sequence": 2,
"matchingtext": "",
"weight": 0
}, {
"text": "dog",
"itemID": "3",
"checked": 0,
"sequence": 3,
"matchingtext": "",
"weight": 0
}],
"2": [{
"text": "pizza",
"itemID": "1",
"checked": 1,
"sequence": 1,
"matchingtext": "",
"weight": 0
}, {
"text": "horse",
"itemID": "2",
"checked": 0,
"sequence": 2,
"matchingtext": "",
"weight": 0
}, {
"text": "paper",
"itemID": "3",
"checked": 0,
"sequence": 3,
"matchingtext": "",
"weight": 0
}]
},
"wbmode": "dd",
"wbanswertype": "sc"
}
Since its not having any specific structure I cant de-serialize it using some structured classes.
So how can I traverse across all the objects of items such as in this case 1 and 2
I would recommend using the JSON.NET library (available via NuGet). Once you add reference to it in your project and import the library to your class, you can traverse through the JSON structure like this:
Dim jsonString = "{""items"":{""1"":[{""text"":""Man"",""itemID"":""1"",""checked"":1,""sequence"":1,""matchingtext"":"""",""weight"":0},{""text"":""goat"",""itemID"":""2"",""checked"":0,""sequence"":2,""matchingtext"":"""",""weight"":0},{""text"":""dog"",""itemID"":""3"",""checked"":0,""sequence"":3,""matchingtext"":"""",""weight"":0}],""2"":[{""text"":""pizza"",""itemID"":""1"",""checked"":1,""sequence"":1,""matchingtext"":"""",""weight"":0},{""text"":""horse"",""itemID"":""2"",""checked"":0,""sequence"":2,""matchingtext"":"""",""weight"":0},{""text"":""paper"",""itemID"":""3"",""checked"":0,""sequence"":3,""matchingtext"":"""",""weight"":0}]},""wbmode"":""dd"",""wbanswertype"":""sc""}"
Dim j As JObject = JObject.Parse(jsonString)
For Each item As JProperty In j.Item("items")
Dim itemObjects As JToken = item.Value
For Each i As JObject In itemObjects
For Each p In i
Debug.Print(p.Key.ToString & " = " & p.Value.ToString)
Next
Next
Next