This Should be Easy - Percent of one Value of a Field

So here’s the deal. I am a noob. I’ve been somewhat forced into this but it is what it is. Forgive me ahead of time for not knowing the syntax or this or that. I assure you I have read a ton, I’m just not as smart as you probably are - so thanks in advance.

Here is what I have. A Kibana index with about 1100 records. Each record has probably 20 fields. I have one field that lists the “point of contact” for the “application name” (another field). I also have a field that is the “portfolio” (ie Security, HR, Finance, etc).

All I want to do is create a bar or pie chart that shows the total number of records and then the percentage that are missing. I want to be able to drill in for each portfolio but I can do that with a control filter.

I also want to create a stacked bar chart that has the portfolio name on the Y-Axis and then the percent complete of their “point of contact” field. In other words if the security portfolio has 50 apps and 25 of them have empty an point of contact field then they are 50% complete. In short, any entry that isn’t blank “” I want to put into a complete bucket. And I want to compare the missing/empty fields with the total records.

I know I could do this with a scripted field but my Kibana offering doesn’t allow scripted fields (long story).

So I think Vega is the way to do this but even referencing fields has been a bit of a nightmare for me.

Any ideas or nudges in the wrong way would be greatly appreciated.

dandcp,

Just to be clear, for chart 1 you just want like pie chart with 2 slices, one that represents number of records with a POC and number of records without? If so, then you do an aggs - terms query for the POC and include this:
{"aggs": {"2": {"terms": {"field": "pocField", "order": {"_count": "desc"}, "missing": "MISSING", "size": 500}}}

Once you have that, you can do your format ("format": {"property": "aggregations.2.buckets"}.

Then for your transforms, you'll need to do a project to extract key and doc_count as key and value. Then you do another transform for an expression: {"type": "formula", "as": ["key"], "expr": "datum.key == 'MISSING' ? 'MISSING' : 'INCLUDED'"}. Finally, you'll do an aggregate transform and groupby key and sum by value. Now you'll have two items in your table: "INCLUDED" and "MISSING". You can name it however you need to but that is the basic outcome here.

For your second visualization, you'll need to get total numbers for each portfolio AND the comparison of those with and without the POCs. Basically the aggregate will need to be by portfolio by cardinality of POC with the MISSING setting from before for your data call. Then do a few transforms until you get a line for each portfolio as key and total as value1 and missing number as value2.

Visualizing this can happen in several different ways. Regardless what you choose, you'll create a group marking that calls that data. Then you'll need to set a bars mark under the group that will be the total (using value1). After that mark (but in the same group), you'll make another bars mark that is based on value2 (the MISSING count). From here, just make bar1 like grey fill and bar 2 with a different color so that it looks like you are seeing percent of each is missing.

If I erred in understanding please let me know and I'll try to help as best as I can. One thought, for that second viz, if you want to show percentage completed then you'll need a formula transform to do (value1-value2) as number completed and then (value1-value2)/value1 for the percentage complete.

Happy Vega'ing and let me know if that works or if you need more help!

-Midas

Midas,

Truly appreciate the thorough explanation. I am going to dig into what you said and see if I can get it implemented. I'm sure I'll run into an issue, though it'll likely be syntax related.

One really random question, when I look at the syntax I see a lot of examples that put double quotes around things like "data" and "transform" and so on. Yet then I see other examples where double quotes aren't used. Is there a hard & fast rule that I should follow?

One of the issues I seem to be running into is that our Kibana implementation is a compliment of another tool that we are using. So we don't manage our Elasticsearch implementation. And because of that we are using an older version (6.8.10).

I bring that up because when I run into syntax errors I'm wondering, at times, if it's related to me trying to do something that isn't supported in my version of Kibana. Is there a quick or easy way to see, for example, what options for "transform" exist in this specific software version?

Once again thanks for the feedback. It's embarrassing how much time I've spent on this already, but such is the learning process I guess.

Okay - so this will likely be embarrassing since my syntax is obviously messed up. One thing I am having a really hard time wrapping my head around is what is a subset of what. I am not a coder by nature, but I have written things in python and other languages when the need arises. I guess what I am struggling with is things like "is transform part of data" or is "format part of transform"? I know those seem like basics, but even when I look at examples online I find different properties nested in different areas. And when I try and type up code and try it out I keep getting random errors about "missing keys and expecting quotes" and bunch of other stuff. So I've tried to dial it back a bit and make sure each step is working by looking at the dev tools on the browser. For whatever reason I'm getting errors every time I try the first transform. I'm copying the code of what I have so far. Can you point me in the right direction as to what is going on? I know the parts looking up the index are working b/c if I take out the aggregation stuff I don't get an error and I see the response in the dev tools.

 {
	$schema: https://vega.github.io/schema/vega/v3.3.1.json
	padding: 5
	data: [
	{
		name: source
		url: {
			%context%: true
			index: my_custom_index
			body: {size: 10000}
			}
		transform: [
			{
			"type": "aggregate": {
			"aggs": {"2" {"terms": {"field": "business_poc", "order": {"_count": "desc"}, "missing": "MISSING", "size": 500}
			}
			}
			}
			}
	]
	format: {"property": "aggregations.2.buckets"}
	}
	]
	}

I've made a bit of progress. I can get everything to work up until I get to the transform. If I take that part out I don't get any errors, but as the current code stands I get an error that says data.transform.Foreach is not a function.

Here's what I have so far.

{
	$schema: https://vega.github.io/schema/vega/v3.3.1.json
	padding: 5
	data: [
	{
		name: source
		url: {
			%context%: true
			index: my_custom_index
			body: {size: 10000}
			},
      type: filter
        expr: datum._source['annual_recurring_cost'] != null && datum._source['technical_risk'] != null && datum._source['business_value'] != null && datum._source['technical_value'] != null
      type: project
      fields: [
      _source.name
      _source['business_poc']
      _source['portfolio']
            ]
         as: ["name", "bpoc", "portfolio"]
		transform:
		 type: aggregate: { aggs: {"2" {"terms": {"field": "business_poc", "order": {"_count": "desc"}, "missing": "MISSING", "size": 500}
	format: {"property": "aggregations.2.buckets"}
	}
	]
	}

dandcp,

Okay, so definitely a bit to unpack here :-).

  1. Syntax: You can use the double quotes or write it in HJSON. There is a little wrench icon in the Vega code part in Kibana that you can click on to automatically reformat your code in HJSON. I tend use the JSON approach (double quotes) to make sure that I don't mess anything up. In HJSON, you have to have everything on a new line and that just hurts my head to look at. Personal preference.
  2. Version: We were using Kibana 6.5.4 for the longest time so I am well versed with Vega 3.3.1. Just now getting into 4.3.0 which is fantastic...but different. A lot of the things that I wanted to do in 3.3.1 I had to write workarounds to (like polar coordinates) and now I can see that in 4.3.0. But I digress...
  3. Data calls in Vega in Kibana are URL calls to your Elasticsearch cluster. The idea here is that you have the name, url, format, and transform sections. Name is, well, the name. URL is the data call to ElastiCsearch. Format transforms Elasticsearch returns in to more of a table-like structure. Finally, transform is an essential part of Vega code that we use to make sure that the final output of the data call resembles that table like format (i.e. key, value).
  4. See below for some changes to your code. Hope this helps!

{
"$schema": "https://vega.github.io/schema/vega/v3.3.1.json",
"padding": 5, // Padding isn't really necessary, Kibana view panels tend to handle this enough. Totally your call though.
"data": [
{
"name": "source",
"url": {
"%context%": true,
"index": "my_custom_index",
"body": {
"size": 0,
// This is an aggs query, you had just a hits.hits query here earlier but we need to aggregate instead of just retireve all records.
"aggs": {"2" {"terms": {"field": "business_poc", "order": {"_count": "desc"}, "missing": "MISSING", "size": 500}}}
}
},
"format": {"property": "aggregations.2.buckets"},
"transform": [
{
"type": "project",
"fields": ["key", "doc_count"],
"as": ["key", "value"]
// This renames your resultant fields as key and value. Key will be your bars and value the size of your bars.
},
{
"type": "formula",
"as": ["key"],
"expr": "datum.key && datum.key == 'MISSING' ? 'Missing' : 'Present'"
// This formula basically overwrites the key with either Missing or Present, so you can show this for a pie chart or basic bar chart. Obviously this won't work for the second visualization.
},
{
"type": "aggregate",
"groupby": ["key"],
"fields": ["value"],
"ops": ["sum"],
"as": ["value"]
// This groups all of those business_poc results as either present or missing so that you should just get 1 record with Present along with a value of how many are present and Missing with a value of how many are Missing.
}
]
}
]
}

Midas

Once again, thanks for not only the assistance but for taking the time to explain things. I am curious what sort of debug options I have. I took the updates to the code and plugged into Kibana and I keep getting "internal server error" - which is super helpful.

I have tried to isolate what is causing the issue, but the only thing I can think to do is to open up the web developer tools on the browser and look at the requests. Basically the minute I add the "agg" statement it throws an "internal server error". What am I missing? And is there any way to tell why it's throwing the error?

This works (although it doesn't do anything, but I can see that it returns 1103 records in the dev tools.

{
 "$schema": "https://vega.github.io/schema/vega/v3.3.1.json",
 "padding": 5,
 "data": [
  {
  "name": "source",
  "url": {
  "%context%": true,
  "index": "my_custom_index",
  "body": {
  "size": 5000,
 // "aggs": { 
//    "2": {
//    "terms": {
//    "field": "business_poc", 
//    "order": {
//    "_count": "desc"},
//    "missing": "MISSING", 
//    "size": 5000}
//    }
//    }
  }
  },
//  "format": {
//    "property": "aggregations.2.buckets"
//    }
//  "transform": [
//  {
//    "type": "project",
//    "fields": ["key", "doc_count"],
//    "as": ["key", "value"]
//  },
//  {
//    "type": "formula",
//    "as": ["key"],
//    "expr": "datum.key && datum.key == 'MISSING' ? 'Missing' : 'Present'"
//  },
//  {
//    "type": "aggregate",
//    "groupby": ["key"],
//    "fields": ["value"],
//    "ops": ["sum"],
//    "as": ["value"]
}
]
}
{
    "took": 0,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 1103,
        "max_score": 0,
        "hits": []
    }
}

But, the minute I add in the "aggs" statement I just get an internal error.

{
 "$schema": "https://vega.github.io/schema/vega/v3.3.1.json",
 "padding": 5,
 "data": [
  {
  "name": "source",
  "url": {
  "%context%": true,
  "index": "gdit_custom_index",
  "body": {
  "size": 5000,
  "aggs": { 
    "2": {
    "terms": {
    "field": "business_poc", 
    "order": {
    "_count": "desc"},
    "missing": "MISSING", 
    "size": 5000}
    }
    }
  }
  },
//  "format": {
//    "property": "aggregations.2.buckets"
//    }
//  "transform": [
//  {
//    "type": "project",
//    "fields": ["key", "doc_count"],
//    "as": ["key", "value"]
//  },
//  {
//    "type": "formula",
//    "as": ["key"],
//    "expr": "datum.key && datum.key == 'MISSING' ? 'Missing' : 'Present'"
//  },
//  {
//    "type": "aggregate",
//    "groupby": ["key"],
//    "fields": ["value"],
//    "ops": ["sum"],
//    "as": ["value"]
}
]
}
{
    "statusCode": 500,
    "error": "Internal Server Error",
    "message": "An internal server error occurred"
}

I like trying to figure things out by myself, but I'm really lost as I can't find any details as to why this isn't working. As I said, when I try and break it down one piece at a time it breaks at the first bit of code after grabbing the index. I googled and found numerous examples of the aggs statement and the syntax seems fine (not to mention when it's a syntax issues I normally get a syntax error).

Thanks in advance!

Midas,

Okay, I finally figured out what was going on. I had to referenced the "keyword" for business_poc, and after I did that it started working.

Dumb question, can you explain the expression?

I understand everything up until that part. Also, when I debug I am seeing all of the different values as well as the missing. For example, it looks like this:

aggregations": {
        "2": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
                {
                    "key": "",
                    "doc_count": 559
                },
                {
                    "key": "MISSING",
                    "doc_count": 324
                },
                {
                    "key": "Other Person",
                    "doc_count": 12
                },
                {
                    "key": "Random Name",
                    "doc_count": 9
                },

...so I get that I've got names of PoCs as "keys" and I have "MISSING" as a "key" (and I also have empty strings, which are essentially missing - the issue there is that Elasticsearch is counting the records that don't have the field as missing and not counting empty strings as missing - I can work on that).

...so how does it know to take all of the "names" and make them "complete" and take all of the missing and mark them missing?

Thanks again!

Midas,

Sooo, I've tried adding in some things for the pie chart - hoping that the values were actually being calculated the right way.

The good news is I am not getting any errors. The bad news is that the pie chart isn't displaying.

Here's what I have so far:

{
 "$schema": "https://vega.github.io/schema/vega/v3.3.1.json",
 "padding": 5,
  "signals": [
    {
      "name": "startAngle", "value": 0,
      "bind": {"input": "range", "min": 0, "max": 6.29, "step": 0.01}
    },
    {
      "name": "endAngle", "value": 6.29,
      "bind": {"input": "range", "min": 0, "max": 6.29, "step": 0.01}
    },
    {
      "name": "padAngle", "value": 0,
      "bind": {"input": "range", "min": 0, "max": 0.1}
    },
    {
      "name": "innerRadius", "value": 0,
      "bind": {"input": "range", "min": 0, "max": 90, "step": 1}
    },
    {
      "name": "cornerRadius", "value": 0,
      "bind": {"input": "range", "min": 0, "max": 10, "step": 0.5}
    },
    {
      "name": "sort", "value": false,
      "bind": {"input": "checkbox"}
    }
  ],
 "data": [
  {
  "name": "source",
  "url": {
  "%context%": true,
  "index": "my_custom_index",
  "body": {
  "size": 0,
  "aggs": { 
    "2": {
    "terms": {
    "field": "business_poc.keyword", 
    "order": {
    "_count": "desc"},
    "missing": "MISSING", 
    "size": 500}
    }
    }
  }
  },
  "format": {
    "property": "aggregations.2.buckets"
    }
  "transform": [
  {
    "type": "project",
    "fields": [
    "key", 
    "doc_count"
    ]
    "as": ["key", "value"]
    // This renames your resultant fields as key and value. Key will be your bars and value the size of your bars.
  },
  {
    "type": "formula",
    "as": ["key"],
    "expr": "datum.key && datum.key == 'MISSING' ? 'Missing' : 'Present'"
    // This formula overwrites the key with either Missing or Present, so you can show this for a pie chart or basic bar chart.
  },
{
    "type": "aggregate",
    "groupby": ["key"],
    "fields": ["value"],
    "ops": ["sum"],
    "as": ["value"]
    },
    // This groups all of those business_poc results as either present or missing so that we should get 1 record with Present along with a value and Missing with a value
        {
          "type": "pie",
          "field": "value",
          "startAngle": {"signal": "startAngle"},
          "endAngle": {"signal": "endAngle"},
          "sort": {"signal": "sort"}
        }
      ]
  "scales": [
    {
      "name": "color",
      "type": "ordinal",
      "domain": {"data": "key", "field": "key"},
      "range": {"scheme": "category20"}
    }
  ],
  "marks": [
    {
      "type": "arc",
      "from": {"data": "source"},
      "encode": {
        "enter": {
          "fill": {"scale": "color", "field": "key"},
          "x": {"signal": "width / 2"},
          "y": {"signal": "height / 2"}
        },
        "update": {
          "startAngle": {"field": "startAngle"},
          "endAngle": {"field": "endAngle"},
          "padAngle": {"signal": "padAngle"},
          "innerRadius": {"signal": "innerRadius"},
          "outerRadius": {"signal": "width / 2"},
          "cornerRadius": {"signal": "cornerRadius"}
        }
  }
}
]
}
]
}

dandcp,

Alright, more to work with :). Let's see how I can help.

  1. VEGA_DEBUG is your debug console. So hit ctrl+shift+j, then use VEGA_DEBUG.view.data("source") to see your data output and test it as you go. You cannot look at Marks in this way, mostly just signals and data.
  2. For MISSING, Elasticsearch is just counting up total number of records that do not have that field in the document. Then it summarizes that here and tells you how many are missing.
  3. Expression: The expression basically was written so that you could take all of the MISSING and call it MISSING, and all those that are not missing as Present. In this regard, you would have just two records left after the transform, a key of Missing and a key of Present. Just an example here, but in this way you could see how many were there (the original problem) versus how many are missing. The aggregate transform at the end there just summarizes all of those Present entries.
  4. Expression Update: Now that I see your data, and that you have blank entries in there too, you probably want the formula to be like: datum.key && (datum.key == 'MISSING' || datum.key == '') ? 'Missing' : 'Present'. What is happening here is we are saying if the key field exists and that key is either empty or filled in with 'MISSING', then call it 'Missing'. Otherwise, call it 'Present'.
  5. Updated your code a bit, had a few close - open issues. I also added in a little styling for you to add some flair. Please let me know if this works, it should but you never know.

{
"$schema": "https://vega.github.io/schema/vega/v3.3.1.json",
"autosize": {"type": "fit", "contains": "content", "resize": true},
"title": "dandcp Awesomeness",
"config": {"kibana": {"hideWarnings": true}},
"signals": [
{
"name": "startAngle", "value": 0,
"bind": {"input": "range", "min": 0, "max": 6.29, "step": 0.01}
},
{
"name": "endAngle", "value": 6.29,
"bind": {"input": "range", "min": 0, "max": 6.29, "step": 0.01}
},
{
"name": "padAngle", "value": 0,
"bind": {"input": "range", "min": 0, "max": 0.1}
},
{
"name": "innerRadius", "value": 0,
"bind": {"input": "range", "min": 0, "max": 90, "step": 1}
},
{
"name": "cornerRadius", "value": 0,
"bind": {"input": "range", "min": 0, "max": 10, "step": 0.5}
},
{
"name": "sort", "value": false,
"bind": {"input": "checkbox"}
},
{
"name": "strokeWidth",
"value": 2
}
],
"data": [
{
"name": "source",
"url": {
"%context%": true,
"index": "my_custom_index",
"body": {
"size": 0,
"aggs": {
"2": {
"terms": {
"field": "business_poc.keyword",
"order": {
"_count": "desc"
},
"missing": "MISSING",
"size": 500
}
}
}
}},
"format": {"property": "aggregations.2.buckets"},
"transform": [
{
"type": "project",
"fields": ["key", "doc_count"],
"as": ["key", "value"]
// This renames your resultant fields as key and value. Key will be your bars and value the size of your bars.
},
{
"type": "formula",
"as": ["key"],
"expr": "datum.key && (datum.key == 'MISSING' || datum.key == '') ? 'Missing' : 'Present'"
// This formula overwrites the key with either Missing or Present, so you can show this for a pie chart or basic bar chart.
},
{
"type": "aggregate",
"groupby": ["key"],
"fields": ["value"],
"ops": ["sum"],
"as": ["value"]
// This groups all of those business_poc results as either present or missing so that we should get 1 record with Present along with a value and Missing with a value
},
{
"type": "pie",
"field": "value",
"startAngle": {"signal": "startAngle"},
"endAngle": {"signal": "endAngle"},
"sort": {"signal": "sort"}
}
]
}
],
"scales": [
{
"name": "color",
"type": "ordinal",
"domain": {"data": "source", "field": "key"},
"range": {"scheme": "tableau10"}
}
],
"marks": [
{
"type": "arc",
"from": {"data": "source"},
"zindex": 1,
"interactive": true,
"encode": {
"enter": {
"fill": {"scale": "color", "field": "key"},
"x": {"signal": "width / 2"},
"y": {"signal": "height / 2"},
"tooltip": {"signal": "datum"},
"cursor": {"value": "cursor"}
},
"update": {
"startAngle": {"field": "startAngle"},
"endAngle": {"field": "endAngle"},
"padAngle": {"signal": "padAngle"},
"innerRadius": {"signal": "innerRadius"},
"outerRadius": {"signal": "if(width >= height, height, width) / 2"},
"cornerRadius": {"signal": "cornerRadius"},
"stroke": {"signal": "scale('color', datum.key)"},
"strokeWidth": {"signal": "strokeWidth"},
"fillOpacity": {"value": 0.9}
},
"hover": {
"fillOpacity": {"value": 0.6}
}
}
}
]
}

Midas,

I wanted to thank you for all of your help. The pie chart is displaying now, though I'm trying to put some finishing touches on it. At first I liked the interactive "adjust the pie chart" stuff, but in the end I think it's kind of pointless so I fiddled around and took out the "binding" part of the code and that seems to remove it remove it from the display. I also didn't want the angles to display when I hover over the pie chart so I removed the "datum" reference and put "datum.value" so it shows the number. I want to have it show the key and the value, but I can't figure out how to add two references. I looked it up and it seems like it should be an array:

"tooltip": [{"signal": "datum.value"}{"signal":"datum.key"}]

but that doesn't seem to work as I either get an error or the last value that I put (i.e. datum.key) is the only one that is shown.

I figured out how to add a legend, though that was harder than I had anticipated. One thing I cannot for the life of me figure out is how to change the size of the title. I have looked at "titlefontSize" and "fontSize" but nothing seems to work. Not sure if this is a bug or something that I am doing wrong.

Lastly - at least for now, the calculation seemed to be working until I looked a little closer. As of now I have 1103 records in my index. Of those 1103 records 324 of them don't even have the field in their record (if I'm using the wrong syntax feel free to correct me). Of those 1103, 559 have the field, but the field is empty, which means 220 of the records have the field and have it populated with someone's name. So here's the catch, the pie chart is only finding the records that don't have the POC field. So it's showing 324 as missing and all of the empty strings as well as the 220 complete as "present" (or complete). I've tried messing around the formula but nothing is working yet. Rather than looking for the empty string, I was thinking that perhaps I could say datum.key == MISSING or the key length is 0. But I'm not sure that is even a field...it doesn't error out when I put datum.key.length but it also doesn't change the calculation.

Any thoughts?

"type": "formula",
"as": ["key"],
"expr": "datum.key && (datum.key == 'MISSING' || datum.key.length == '0') ? 'Missing' : 'Complete'"

And for what it's worth, this is the entire code:

{
"$schema": "https://vega.github.io/schema/vega/v3.3.1.json",
 // "width": 400,
 // "height": 400,
 "autosize": "fit" 
 // {"type": "fit", "contains": "content", "resize": true},
"title": {text: "Business PoC Completion", "fontSize": 24},
"config": {"kibana": {"hideWarnings": true}},
"signals": [
{
"name": "startAngle", "value": 0,
// the bind statements will create a slider to allow dynamic adjustments to the pie chart
// "bind": {"input": "range", "min": 0, "max": 6.29, "step": 0.01}
},
{
"name": "endAngle", "value": 6.29,
// "bind": {"input": "range", "min": 0, "max": 6.29, "step": 0.01}
},
{
"name": "padAngle", "value": 0,
// "bind": {"input": "range", "min": 0, "max": 0.1}
},
{
"name": "innerRadius", "value": 0,
// "bind": {"input": "range", "min": 0, "max": 90, "step": 1}
},
{
"name": "cornerRadius", "value": 0,
// "bind": {"input": "range", "min": 0, "max": 10, "step": 0.5}
},
{
"name": "sort", "value": false,
//  "bind": {"input": "checkbox"}
},
{
"name": "strokeWidth",
"value": 2
}
],
"data": [
{
"name": "source",
"url": {
"%context%": true,
"index": "my_custom_index",
"body": {
"size": 0,
"aggs": {
"2": {
"terms": {
"field": "business_poc.keyword",
"order": {
"_count": "desc"
},
"missing": "MISSING",
"size": 5000
}
}
}
}},
"format": {"property": "aggregations.2.buckets"},
"transform": [
{
"type": "project",
"fields": ["key", "doc_count"],
"as": ["key", "value"]
// This renames the business_poc.keyword and count fields as key and value. Key = bars & value = size.
},
{
"type": "formula",
"as": ["key"],
"expr": "datum.key && (datum.key == 'MISSING' || !datum.key.length > '0') ? 'Missing' : 'Complete'"
// This formula overwrites the key with either Missing or Complete, so you can show this for a pie chart or basic bar chart.
},
{
"type": "aggregate",
"groupby": ["key"],
"fields": ["value"],
"ops": ["sum"],
"as": ["value"]
// This groups all of those business_poc results as either present or missing so that we should get 1 record with Present along with a value and Missing with a value
},
{
"type": "pie",
"field": "value",
"startAngle": {"signal": "startAngle"},
"endAngle": {"signal": "endAngle"},
"sort": {"signal": "sort"}
}
]
}
],
"scales": [
{
"name": "color",
"type": "ordinal",
"domain": {"data": "source", "field": "key"},
"range": {"scheme": "tableau10"}
}
],
"marks": [
{
"type": "arc",
"from": {"data": "source"},
"zindex": 1,
"interactive": true,
"encode": {
"enter": {
"fill": {"scale": "color", "field": "key"},
"x": {"signal": "width / 2"},
"y": {"signal": "height / 2"},
"tooltip": {"signal": "datum.value"}
"cursor": {"value": "cursor"}
},
"update": {
"startAngle": {"field": "startAngle"},
"endAngle": {"field": "endAngle"},
"padAngle": {"signal": "padAngle"},
"innerRadius": {"signal": "innerRadius"},
"outerRadius": {"signal": "if(width >= height, height, width) / 2"},
"cornerRadius": {"signal": "cornerRadius"},
"stroke": {"signal": "scale('color', datum.key)"},
"strokeWidth": {"signal": "strokeWidth"},
"fillOpacity": {"value": 0.9}
},
"hover": {
"fillOpacity": {"value": 0.6}
}
}
}
]
"legends": [
  {
    "orient": "top",
    "fill": "color",
    "encode": {
      "title": {
        "update": {
          "fontSize": {"value": 18}
        }
      },
      "labels": {
        "interactive": true,
        "update": {
          "fontSize": {"value": 18},
          "fill": {"value": "black"}
        },
        "hover": {
          "fill": {"value": "value"}
        }
      },
      "symbols": {
        "update": {
          "stroke": {"value": "transparent"}
        }
      },
      "legend": {
        "update": {
          "stroke": {"value": "#ccc"},
          "strokeWidth": {"value": 0}
        }
      }
    }
  }
]
}

Midas,

Is there an easy way to debug things? When I used to write irules for F5, I would sometimes get knee deep into the code and kind of want to check on what I thought the different variables were, especially when I was doing calculations to make sure I was on the right path. So I had ways to basically write code that would - for example - display my current variables, or data. I'm curious if there is way for me to display an output so I can check where I'm at - kind of like a writing to standard out. Not sure if that makes sense or not, but just way to do a sanity check.

Thanks again!

dandcp,

No problem, happy to help. It can be a bit daunting at times, especially since the examples are mostly devoid of styling and functionality. Just some notes and answers for ye:

  • Yeah, binds are great for discovery and testing but, in the end, not always worth it as they take space away from the viewbox.
  • Tooltip: "tooltip": {"signal": "{'Key': datum.key, 'Value': format(datum.value, ',.0f')}"}
  • Tooltip Note: So, multi-line tooltips you do like above, you name a line, add the value. Then the comma serves as the new line separator. I added a bit of a number formatter for you just in case.
  • If that is title, then you'll need this config. I set it to make the title size 28, black color, and in sans-serif font: "config": {"kibana": {"hideWarnings": true}, "title": {"fontSize": {"value": 28}, "font": {"value": "sans-serif"}, "fill": {"value": "black"}}}
  • For the formula, not really sure. You'll still need datum.key == '' in there as you are getting results back for empty records. Maybe you could do the inverse. Like "datum.key && datum.key.length > 0 ? 'Present' : 'Missing'". Try that, see what happens. Otherwise you may have to write a script...

Good luck!

-Midas

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.