R: Nested data.table to JSON - r

I want to get from a data.table like this
temp <- data.table(data = list(data.table(a = 1:2,b=1:2)), type = "A")
data
type
<data.table[2x2]>
A
to a JSON like this
{
"group":
{
"data": [
{
"a": 1,
"b": 1
},
{
"a": 2,
"b": 2
}
],
"type": "A"
}
}
The Problem is I always end up with an additional array "[" for group.
What I have tried is tidyr::nest and
temp2 <- temp[, list(group=list(.SD))]
jsonlite::toJSON(temp2,pretty = TRUE, auto_unbox = TRUE)
temp3 <- temp[, (list(group=list(as.list(.SD))))]
jsonlite::toJSON(temp3,pretty = TRUE, auto_unbox = TRUE)
Is there an "easy" solution for my problem?
Thanks
edit more complex example
temp <-
data.table(
id1 = 1:6,
id2 = c(rep("A", 2), rep("B", 2), rep("C", 2)),
data = rep(list(data.table(
a = 1:2, b = 1:2
)), 6),
type = "test"
)
nest1 <- temp[, list(list(.SD)),by=.(id1,id2)] %>% setnames("V1","group")
nest1[, type:="B"]
nest2 <- nest1[, list(list(.SD)),by=.(id2)] %>% setnames("V1","data")
nest2[, type:="C"]
nest3 <- nest2[, list(list(.SD)),by=.(id2)] %>% setnames("V1","group")
jsonlite::toJSON(nest3, pretty = TRUE)
desired output (shortend):
Group should only contain objects and no arrays
[
{
"id2": "A",
"group": {
"data": [
{
"id1": 1,
"group": {
"data": [
{
"a": 1,
"b": 1
},
{
"a": 2,
"b": 2
}
],
"type": "test"
},
"type": "B"
},
{
"id1": 2,
"group": {
"data": [
{
"a": 1,
"b": 1
},
{
"a": 2,
"b": 2
}
],
"type": "test"
},
"type": "B"
}
],
"type": "C"
}
},
{
"id2": "B",
"group": {
"data": [],
"type": "C"
}
}
]

We could use jq to do the unboxing as a post-processing step, since jsonlite doesn't seem to allow for this specific use case:
jsonlite::toJSON(nest3, pretty = TRUE) %>%
jqr::jq('walk(if type=="array" and length==1 then .[0] else . end)')
The jq bit is taken from jq ~ is there a better way to collapse single object arrays?

Related

R data frame to JSON Hierarchy

I have the following data frame:
fakedat<-data.frame(name=c("Holdingcompany","Holdingcompany","company1","company1","company2","company2"),children=c("company1","company2","company4","company3","company5","company6"),info=c("text1","text2","text3","text5","othertext","other_text"),percentage=c("100%","100%","60%","75%","80%","70%"))
The output I am hoping is the following:
{"name": "Holdingcompany",
"children": [
{
"name": "company1",
"tooltip": "text1",
"percentage": "100%",
"children": [
{
"name": "company4",
"tooltip": "text3",
"percentage": "60%"
},
{
"name": "company3",
"tooltip": "text5",
"percentage": "75%"
}
]
},
{
"name": "company2",
"tooltip": "text2",
"percentage": "100%",
"children": [
{
"name": "company5",
"tooltip": "othertext",
"percentage": "80%"
},
{
"name": "company6",
"tooltip": "other_text",
"percentage": "70%"
}
]
}
]
}
I have attempted a couple different methods of parsing including:
How to write to json with children from R
But unfortunately I wasn't able to apply the above code to this situation properly to the the children in lists the way I was hoping.
Attempting to apply some of the solution from the below mentioned possible duplicate, I'm running into a recursion error: "C stack usage too close to limit" as the function appears to call itself.
##Adding in IDs
fakedat<-data.frame(id=c(1,2,3,4,5,6),name=c("Holdingcompany","Holdingcompany","company1","company1","company2","company2"),
children=c("company1","company2","company4","company3","company5","company6"),
info=c("text1","text2","text3","text5","othertext","other text"),
percentage=c("100%","50%","60%","75%","80%","70%"))
get_node <- function(df, id) {
node <- as.list(df[df$id == id, c("name", "info",
"percentage","id")])
names(node) = c("name", "info", "percentage","id")
id1<-df[df$id==id,]$children
if (!is.na(id1)){
child1 <- get_node(df, id)
if(child1$name == node$name){
node$children <- list(child1)}
node
}
}
jsonlite::toJSON(get_node(fakedat,6), pretty = TRUE, auto_unbox =
TRUE)`
Error: C stack usage 7972496 is too close to the limit
Consider preparing the relationships of parent to child with merge, then walk down each level of root / parent / child to build nested lists with nested lapply:
Data Preparation
### MERGE DATA
merge_df <- merge(fakedat, fakedat, by.x="children", by.y="name")
merge_df
# children name info.x percentage.x children.y info.y percentage.y
# 1 company1 Holdingcompany text1 100% company4 text3 60%
# 2 company1 Holdingcompany text1 100% company3 text5 75%
# 3 company2 Holdingcompany text2 100% company5 othertext 80%
# 4 company2 Holdingcompany text2 100% company6 other_text 70%
nested_df <- unique(merge_df[c("children", "name", "info.x", "percentage.x")])
nested_df
# children name info.x percentage.x
# 1 company1 Holdingcompany text1 100%
# 3 company2 Holdingcompany text2 100%
top_level_val <- unique(merge_df$name)
top_level_val
# [1] "Holdingcompany"
JSON Build
output <- lapply(top_level_val, function(root) {
root_lst <- list(
name = root
)
root_lst$children <- lapply(1:nrow(nested_df), function(i) {
chld_mrg <- merge(nested_df[nested_df$children == nested_df$children[i],], merge_df)
parent_lst <- list(
name = nested_df$children[i][1],
tooltip = nested_df$info.x[i][1],
percentage = nested_df$percentage.x[i][1]
)
parent_lst$children <- lapply(1:nrow(chld_mrg), function(j)
list(
name = merge_df$children.y[j][1],
tooltip = merge_df$info.y[j][1],
percentage = merge_df$percentage.y[j][1]
)
)
return(parent_lst)
})
return(root_lst)
})
# CONVERT TO JSON STRING
jdata <- toJSON(output[[1]], pretty=TRUE, auto_unbox=TRUE)
# WRITE TO DISK
fileConn <- file("NestParentChildJSON.json")
writeLines(jdata, fileConn)
close(fileConn)
Output
{
"name": "Holdingcompany",
"children": [
{
"name": "company1",
"tooltip": "text1",
"percentage": "100%",
"children": [
{
"name": "company4",
"tooltip": "text3",
"percentage": "60%"
},
{
"name": "company3",
"tooltip": "text5",
"percentage": "75%"
}
]
},
{
"name": "company2",
"tooltip": "text2",
"percentage": "100%",
"children": [
{
"name": "company4",
"tooltip": "text3",
"percentage": "60%"
},
{
"name": "company3",
"tooltip": "text5",
"percentage": "75%"
}
]
}
]
}

Converting separate data frames to a JSON file for a tidy tree chart

I did not know how to store complex tidy tree data in excel, so I decided to store data for each level in a sheet.
For a simple example, consider the two following dataframes.
for making a tidy tree chart from this dataframes I have tried the following step:
Data
dim_data <- structure(list(dim1 = c("sub1", "sub2", "sub3"), dim2 = c("sub4",
"sub5", NA)), row.names = c(NA, -3L), class = c("tbl_df", "tbl",
"data.frame"))
sub_data <- structure(list(sub1 = c("a", "b", "c"), sub2 = c("d", "f", NA
), sub3 = c("e", "h", NA), sub4 = c("i", "g", NA), sub5 = c("k",
"p", NA)), row.names = c(NA, -3L), class = c("tbl_df", "tbl",
"data.frame"))
Code:
## Function to make each column a list and remove `na`.
list_remove_na <- function(x){
x <- lapply(x, as.list)
x <- sapply(x, function(x) x[!is.na(x)])
x <- sapply(x, unlist)
return(x)
sub_list <- list_remove_na(sub_data)
attach(sub_list)
data_list <- list_remove_na(dim_data)
## Making final list
integrate <- function(x){sapply(x, function(x){ x = get(x)},simplify = F)}
final_list <- sapply(data_list, integrate, simplify = F)
Final list:
final_list
$dim1
$dim1$sub1
[1] "a" "b" "c"
$dim1$sub2
[1] "d" "f"
$dim1$sub3
[1] "e" "h"
$dim2
$dim2$sub4
[1] "i" "g"
$dim2$sub5
[1] "k" "p"
Converting the final list to JSON
library(rjson)
jdata <-toJSON(final_list, indent=1, method="C")
write(jdata, file = "data.json")
JSON File:
{
"dim1":{
"sub1":[
"a",
"b",
"c"
],
"sub2":[
"d",
"f"
],
"sub3":[
"e",
"h"
]
},
"dim2":{
"sub4":[
"i",
"g"
],
"sub5":[
"k",
"p"
]
}
}
Then Using following function from here to make a Parents and children JSON data:
const treeify = (orig, parent) => Object.entries(orig).map(
([k, v]) => (Object.assign({name: k, parent}, typeof v == 'object'
? {children: treeify(v, k)}
: {children: {name: v, parent: k}}
))
)
const convert = (orig) => treeify({Root: orig}, 'null')[0]
const orig =
{
"dim1":{
"sub1":[
"a",
"b",
"c"
],
"sub2":[
"d",
"f"
],
"sub3":[
"e",
"h"
]
},
"dim2":{
"sub4":[
"i",
"g"
],
"sub5":[
"k",
"p"
]
}
}
console.log(convert(orig))
Result:
{
"name": "Root",
"parent": "null",
"children": [
{
"name": "dim1",
"parent": "Root",
"children": [
{
"name": "sub1",
"parent": "dim1",
"children": [
{
"name": "0",
"parent": "sub1",
"children": {
"name": "a",
"parent": "0"
}
},
{
"name": "1",
"parent": "sub1",
"children": {
"name": "b",
"parent": "1"
}
},
{
"name": "2",
"parent": "sub1",
"children": {
"name": "c",
"parent": "2"
}
}
]
},
{
"name": "sub2",
"parent": "dim1",
"children": [
{
"name": "0",
"parent": "sub2",
"children": {
"name": "d",
"parent": "0"
}
},
{
"name": "1",
"parent": "sub2",
"children": {
"name": "f",
"parent": "1"
}
}
]
},
{
"name": "sub3",
"parent": "dim1",
"children": [
{
"name": "0",
"parent": "sub3",
"children": {
"name": "e",
"parent": "0"
}
},
{
"name": "1",
"parent": "sub3",
"children": {
"name": "h",
"parent": "1"
}
}
]
}
]
},
{
"name": "dim2",
"parent": "Root",
"children": [
{
"name": "sub4",
"parent": "dim2",
"children": [
{
"name": "0",
"parent": "sub4",
"children": {
"name": "i",
"parent": "0"
}
},
{
"name": "1",
"parent": "sub4",
"children": {
"name": "g",
"parent": "1"
}
}
]
},
{
"name": "sub5",
"parent": "dim2",
"children": [
{
"name": "0",
"parent": "sub5",
"children": {
"name": "k",
"parent": "0"
}
},
{
"name": "1",
"parent": "sub5",
"children": {
"name": "p",
"parent": "1"
}
}
]
}
]
}
]
}
I do not know where "name": "0" is come from!!!
And tidy tree from here
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Collapsible Tree Example</title>
<style>
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 3px;
}
.node text { font: 12px sans-serif; }
.link {
fill: none;
stroke: #ccc;
stroke-width: 2px;
}
</style>
</head>
<body>
<!-- load the d3.js library -->
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var treeData = [
{
"name": "Root",
"parent": "null",
"children": [
{
"name": "dim1",
"parent": "Root",
"children": [
{
"name": "sub1",
"parent": "dim1",
"children": [
{
"name": "0",
"parent": "sub1",
"children": {
"name": "a",
"parent": "0"
}
},
{
"name": "1",
"parent": "sub1",
"children": {
"name": "b",
"parent": "1"
}
},
{
"name": "2",
"parent": "sub1",
"children": {
"name": "c",
"parent": "2"
}
}
]
},
{
"name": "sub2",
"parent": "dim1",
"children": [
{
"name": "0",
"parent": "sub2",
"children": {
"name": "d",
"parent": "0"
}
},
{
"name": "1",
"parent": "sub2",
"children": {
"name": "f",
"parent": "1"
}
}
]
},
{
"name": "sub3",
"parent": "dim1",
"children": [
{
"name": "0",
"parent": "sub3",
"children": {
"name": "e",
"parent": "0"
}
},
{
"name": "1",
"parent": "sub3",
"children": {
"name": "h",
"parent": "1"
}
}
]
}
]
},
{
"name": "dim2",
"parent": "Root",
"children": [
{
"name": "sub4",
"parent": "dim2",
"children": [
{
"name": "0",
"parent": "sub4",
"children": {
"name": "i",
"parent": "0"
}
},
{
"name": "1",
"parent": "sub4",
"children": {
"name": "g",
"parent": "1"
}
}
]
},
{
"name": "sub5",
"parent": "dim2",
"children": [
{
"name": "0",
"parent": "sub5",
"children": {
"name": "k",
"parent": "0"
}
},
{
"name": "1",
"parent": "sub5",
"children": {
"name": "p",
"parent": "1"
}
}
]
}
]
}
]
}
];
// ************** Generate the tree diagram *****************
var margin = {top: 20, right: 120, bottom: 20, left: 120},
width = 960 - margin.right - margin.left,
height = 500 - margin.top - margin.bottom;
var i = 0;
var tree = d3.layout.tree()
.size([height, width]);
var diagonal = d3.svg.diagonal()
.projection(function(d) { return [d.y, d.x]; });
var svg = d3.select("body").append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
root = treeData[0];
update(root);
function update(source) {
// Compute the new tree layout.
var nodes = tree.nodes(root).reverse(),
links = tree.links(nodes);
// Normalize for fixed-depth.
nodes.forEach(function(d) { d.y = d.depth * 180; });
// Declare the nodes…
var node = svg.selectAll("g.node")
.data(nodes, function(d) { return d.id || (d.id = ++i); });
// Enter the nodes.
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + d.y + "," + d.x + ")"; });
nodeEnter.append("circle")
.attr("r", 10)
.style("fill", "#fff");
nodeEnter.append("text")
.attr("x", function(d) {
return d.children || d._children ? -13 : 13; })
.attr("dy", ".35em")
.attr("text-anchor", function(d) {
return d.children || d._children ? "end" : "start"; })
.text(function(d) { return d.name; })
.style("fill-opacity", 1);
// Declare the links…
var link = svg.selectAll("path.link")
.data(links, function(d) { return d.target.id; });
// Enter the links.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", diagonal);
}
</script>
</body>
</html>
The last level nodes are wrong!!!
Anybody has suggestions for fixing the problems or alternative solutions in R or Python?
Is there R or Python function to convert raw JSON to hierarchical parent and children Json?
How can I rewrite the R function to convert more than two dataframes (scaling it)?
**I have limited knowledge aboutjavascript and JSON
I'll provide a solution for your case of two data frames, but I'd like to find out whether you can store the data in a different format (which can be expanded to more dimensions). I'll illustrate below what I mean.
First, I'll load two packages. The first one (data.table) will help with the data.wrangling, whereas the second (collapsibleTree) will help with the tree visualization:
# Load packages
library(data.table)
library(collapsibleTree)
Next I convert the datasets to data.table as I want to re-format them:
# Convert datasets to data.table format
setDT(sub_data)
setDT(dim_data)
I now convert them to (what is called) 'long' format by using the melt function:
# Convert to long format
sub_data_2 = melt.data.table(sub_data, measure.vars = colnames(sub_data))
dim_data_2 = melt.data.table(dim_data, measure.vars = colnames(dim_data))
At this point, I have sub_data_2:
variable value
1: sub1 a
2: sub1 b
3: sub1 c
4: sub2 d
5: sub2 f
6: sub2 <NA>
7: sub3 e
8: sub3 h
9: sub3 <NA>
10: sub4 i
11: sub4 g
12: sub4 <NA>
13: sub5 k
14: sub5 p
15: sub5 <NA>
and dim_data_2:
variable value
1: dim1 sub1
2: dim1 sub2
3: dim1 sub3
4: dim2 sub4
5: dim2 sub5
6: dim2 <NA>
Next, we merge them:
# Merge
merged = merge(dim_data_2, sub_data_2, by.x = "value", by.y = "variable")
Then do some clean up by renaming columns, and removing those rows with NA entries:
# Cleanup
setnames(merged, colnames(merged), c("sub", "dim", "value"))
merged_2 = merged[complete.cases(merged),]
This is the format I was referring to above:
sub dim value
1: sub1 dim1 a
2: sub1 dim1 b
3: sub1 dim1 c
4: sub2 dim1 d
5: sub2 dim1 f
6: sub3 dim1 e
7: sub3 dim1 h
8: sub4 dim2 i
9: sub4 dim2 g
10: sub5 dim2 k
11: sub5 dim2 p
Is it possible for you to save in this format? Most of what I've done so far is data wrangling. As you will see below, once I have this format, tree plotting is one line of code:
collapsibleTree(merged_2, c("dim", "sub", "value"), collapsed = F)

R plot_ly row or dataframe in PowerBI custom visuals

I am following: http://radacad.com/create-custom-visual-with-r-and-json-part3
Here it is mentioned that with below R code, we can plot the chart:
Values<-data.frame(X,Y,Legend,Row,Column)
g=ggplot(Values, aes(x=X, y=Y,colour = Legend))
I am using similar implementations.
Below code renders blank chart with only axis:
Values <- data.frame(mpg_test, cyl_test)
p <- plot_ly(Values,
x = ~mpg_test,
y = ~cyl_test,
name = "SF Zoo",
type = "bar"
)
Empty chart
Below code also renders empty chart:
Values <- data.frame(mpg_test, cyl_test)
p <- plot_ly(Values,
x = mpg_test,
y = cyl_test,
name = "SF Zoo",
type = "bar"
)
Below code renders correct chart:
Values <- data.frame(mpg_test, cyl_test)
p <- plot_ly(Values,
x = ~mpg_test[1:nrow(Values), ],
y = ~cyl_test[1:nrow(Values), ],
name = "SF Zoo",
type = "bar"
)
Correct chart:
My doubt is, as per the tutorial I must get columns in mpg_test and cyl_test, then why I am getting something like dataframe in here.
Does, plotly handles things differently with the usage of ~ ?
Please help. Also, is there any way I can use the mpg_test and cyl_test without nrow(Values) inside plot_ly
script.r
source('./r_files/flatten_HTML.r')
############### Library Declarations ###############
libraryRequireInstall("ggplot2");
libraryRequireInstall("plotly")
####################################################
################### Actual code ####################
Values <- data.frame(mpt_test, cyl_test)
p <- plot_ly(Values,
x = ~mpt_test[1:nrow(Values), ],
y = ~cyl_test[1:nrow(Values), ],
name = "SF Zoo",
type = "bar"
)
####################################################
############# Create and save widget ###############
#p = ggplotly(p);
internalSaveWidget(p, 'out.html');
####################################################
capabilities.json
{
"dataRoles": [
{
"displayName": "Mileage Per Gallon",
"kind": "GroupingOrMeasure",
"name": "mpg_test"
},
{
"displayName": "Cylinder Size",
"kind": "GroupingOrMeasure",
"name": "cyl_test"
}
],
"dataViewMappings": [
{ "conditions": [
{
"mpg_test": {
"max": 1
},
"cyl_test": {
"max": 1
}
}
],
"scriptResult": {
"dataInput": {
"table": {
"rows": {
"select": [
{
"for": {
"in": "mpg_test"
}
},
{
"for": {
"in": "cyl_test"
}
}
],
"dataReductionAlgorithm": {
"top": {}
}
}
}
},
"script": {
"scriptProviderDefault": "R",
"scriptOutputType": "html",
"source": {
"objectName": "rcv_script",
"propertyName": "source"
},
"provider": {
"objectName": "rcv_script",
"propertyName": "provider"
}
}
}
}
],
"objects": {
"rcv_script": {
"properties": {
"provider": {
"type": {
"text": true
}
},
"source": {
"type": {
"scripting": {
"source": true
}
}
}
}
}
},
"suppressDefaultTitle": true
}

Converting nested JSON to data frame

I am trying to convert a heavily nested json into a proper data frame (proper by tidy standards). An MWE of the json is copied at the end of the question, as I wanted to make sure it captured every element of the json.
I've tried:
library(jsonlite)
library(tidyverse)
dat <- jsonlite::fromJSON('data_toy.json') %>% pluck(1) %>% imap_dfr(~mutate(.x, department = .y))
but this returns:
Error: Columns `time_spent`, `school_breakdown`, `reason_for_taking_course`, `student_years`, `interest_before` must be 1d atomic vectors or lists
I've also tried:
dat <- jsonlite::fromJSON('data_toy.json', simplifyVector = FALSE,
simplifyDataFrame = FALSE, flatten=FALSE)
dat.df <- map_df(dat, ~{
flatten_df(.x[[1]]) %>%
dplyr::mutate(department = names(.x)[1])
})
but this returns:
Error in bind_rows_(x, .id) : Argument 3 must be length 1, not 0
How can I convert this to a data frame?
Data file (data_toy.json):
{
"department": {
"BME": [
{
"course_name": "BMD_ENG_250-0_20: Thermodynamics",
"instructor": "Neha Kamat",
"time_spent": {},
"school_breakdown": {
"Education & SP": 0,
"Communication": 0,
"Graduate School": 0,
"KGSM": 0
},
"reason_for_taking_course": {
"Distribution requirement": 0,
"Major/Minor requirement": 53
},
"student_years": {
"Freshman": 5,
"Sophomore": 37
},
"interest_before": {
"1-Not interested at all": 1,
"2": 5
},
"comments": [
"is amazing and you will love her!",
"Prof. is so nice"
],
"instructor_gender": "F"
},
{
"course_name": "BMD_ENG_250-0_20: Thermodynamics",
"instructor": "Neha Kamat",
"time_spent": {},
"school_breakdown": {
"Education & SP": 0,
"Communication": 0,
"Graduate School": 0,
"KGSM": 0
},
"reason_for_taking_course": {
"Distribution requirement": 0,
"Major/Minor requirement": 53
},
"student_years": {
"Freshman": 5,
"Sophomore": 37
},
"interest_before": {
"1-Not interested at all": 1,
"2": 5
},
"comments": [
"is amazing and you will love her!",
"Prof. is so nice"
],
"instructor_gender": "F"
}
],
"LING": [
{
"course_name": "BMD_ENG_250-0_20: Thermodynamics",
"instructor": "Neha Kamat",
"time_spent": {},
"school_breakdown": {
"Education & SP": 0,
"Communication": 0,
"Graduate School": 0,
"KGSM": 0
},
"reason_for_taking_course": {
"Distribution requirement": 0,
"Major/Minor requirement": 53
},
"student_years": {
"Freshman": 5,
"Sophomore": 37
},
"interest_before": {
"1-Not interested at all": 1,
"2": 5
},
"comments": [
"is amazing and you will love her!",
"Prof. is so nice"
],
"instructor_gender": "F"
},
{
"course_name": "BMD_ENG_250-0_20: Thermodynamics",
"instructor": "Neha Kamat",
"time_spent": {},
"school_breakdown": {
"Education & SP": 0,
"Communication": 0,
"Graduate School": 0,
"KGSM": 0
},
"reason_for_taking_course": {
"Distribution requirement": 0,
"Major/Minor requirement": 53
},
"student_years": {
"Freshman": 5,
"Sophomore": 37
},
"interest_before": {
"1-Not interested at all": 1,
"2": 5
},
"comments": [
"is amazing and you will love her!",
"Prof. is so nice"
],
"instructor_gender": "F"
}
]
}
}
Using flatten = TRUE seems to be the key here:
dat <- jsonlite::fromJSON('data_toy.json', flatten = TRUE)[[1]]
dat %>% bind_rows() %>% mutate(department = rep(names(dat), map_dbl(dat, nrow)))

Leaflet (R) addPopups: coordinates/properties

I'm fairly new to handling spatial data and leaflet in general. I'm having difficulty creating a popup for my map. Basically what I want in the popup is the coordinates of my polygon and one of the properties (the type of class). Below is an test example of my geoJSON file:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {"class": "blah"},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-81.7987060546875,
32.74570253945518
],
[
-81.6229248046875,
32.16631295696736
],
[
-80.958251953125,
32.4263401615464
],
[
-81.2713623046875,
32.791892438123696
],
[
-81.7437744140625,
32.97180377635759
],
[
-81.7987060546875,
32.74570253945518
]
]
]
}
},
{
"type": "Feature",
"properties": {"class": "blah2"},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-82.056884765625,
33.55512901742288
],
[
-81.4471435546875,
33.247875947924385
],
[
-81.40869140625,
33.80653802509606
],
[
-82.078857421875,
33.88865750124075
],
[
-82.40295410156249,
33.58716733904656
],
[
-82.056884765625,
33.55512901742288
]
]
]
}
},
{
"type": "Feature",
"properties": {"class": "blahh3"},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-83.485107421875,
32.930318199070534
],
[
-83.07861328125,
31.863562548378965
],
[
-82.21618652343749,
32.11049589629439
],
[
-82.97973632812499,
33.22030778968541
],
[
-83.726806640625,
33.211116472416855
],
[
-83.485107421875,
32.930318199070534
]
]
]
}
}
]
}
Here is the code I have so far to create my map, but I'm struggling/don't even know where to start on creating a popup that includes my coordinates and property:
blahTest <- geojson_read("/file/path/...", what = "sp")
fpal <- colorFactor("viridis", blahTest$class)
leaflet(blahTest) %>%
addTiles() %>%
addPolygons(stroke = FALSE, smoothFactor = 0.3, fillOpacity = 1,
color = ~fpal(class)) %>%
addLegend(colors = ~fpal, opacity = 1.0, labels = ~fpal) %>%
addPopups()
Thanks in advance!
Overview
Using #patL's suggestion, I used the popup parameter within leaflet::addPolygon() function to add label both the class and coordinates that define each polygon within blahTest.
I saved your sample data as .gejson file and imported it using sf::read_sf() and produced the HTML table within the popup using the htmlTable package after reading How to add an html table to leaflet popup.
# load necessary package
library( htmlTable )
library( leaflet )
library( sf )
# load necessary data
blahTest <-
read_sf(
dsn = "test.geojson"
, layer = "OGRGeoJSON"
)
# map data values to colors
fpal <- colorFactor( palette = "viridis", domain = blahTest$class)
# create map
my.map <-
leaflet( data = blahTest ) %>%
addTiles() %>%
addPolygons( stroke = FALSE
, smoothFactor = 0.3
, fillOpacity = 1
, color = ~fpal( class )
, popup = paste0(
"<b>Class: </b>"
, blahTest$class
, "<br>"
, "<b>Coordinates: </b>"
, "<br>"
, lapply(
X = blahTest$geometry
, FUN = function( i )
htmlTable(
x = i[[1]]
, header = c( "Longitude", "Latitude" )
)
)
) ) %>%
addLegend( pal = fpal
, values = ~class
, labels = ~class
, title = "Legend"
, position = "topright"
, opacity = 1.0 )
# view map
my.map
# end of script #

Resources