top of page

How to Create Data Art in Tableau: Lotus Flowers

Updated: Feb 1, 2023

The following blog by Brian Moore was originally published on Do Mo(o)re With Data May 26 , 2022 and is cross-posted here with permission. Brian is a Tableau Visionary, Tableau Public Ambassador, and a Senior Data Analytics and Viz Consultant for Cleartelligence.


Totally Useless Charts & How to Build Them: Lotus Flowers


Welcome to our new series, Totally Useless Charts & How to Build Them. In each installment of this series we’ll look at one very custom chart, something with almost no real use cases, and we’ll walk through, step by step, how to build it. The purpose of this series isn’t necessarily to teach you how to build these specific useless charts, it’s more about talking through the techniques, the approach, and the thought process behind each chart. Our hope is that seeing how we went about building these will help you with your own custom charts. But if you do somehow find a great use case for one of these charts, by all means, please download the workbook and use it as your own.


In this first installment we’re going to learn how to build Lotus Flowers in Tableau. It’s not a requirement, but it may be a good idea to review Part 1 and Part 2 of the Fun With Curves Series before proceeding. To follow along, you can download the workbook here, and the data here.


Drawing a Lotus Flower


First, let’s take a look at what we’re trying to build. Below is a lotus flower with 10 petals, which means we have a total of 11 polygons; 1 circle and 10 petals. The circle is fairly easy to build using the techniques in Part 1 mentioned above. The petals are a little more complicated. But first thing’s first…we need some data.

Building Your Data Source


Let’s start with our data. For this example we’re going to build 12 lotus flowers and we’re going to use the value from our data source to size the flowers appropriately. We’ll start with the tab titled ‘Source Data’.

Next, we’re going to do some densification to get the number of polygons needed for each of the flowers. Below I have 1 record for the Circle and 24 records for the petals. We’re going to build this in a way that will let you choose how many petals you want to display (up to 24). This data can be found in the ‘Polygons’ tab in the sample data.

Now we’re going to join these two sources together using a join calculation (value of 1 on each side). The result will be 25 records for each of our 12 ‘Base’ records.

Next, we need to do a little more densification, but this time it’s a little trickier. For our circle, we want at least 50 points for a relatively smooth curve. For our petals, we actually need to draw 2 lines for each petal, one for the left side of the petal (Min) and one for the right side of the petal (Max), and then join those together. Pretty confusing right? We’ll talk about this in a lot more detail. This table is a little too large to include a screenshot, but take a look at the ‘Densification’ tab in the sample data.


For our circles, we have 50 records. We have two numerical fields, [Points] and [Order], that both run from 1 to 50 and a [Type] field to identify that these points are for our circles. For our petals, we have 100 records. We still have the same two numerical fields, but the values are a little different. We have an [Order] field that runs from 1 to 100, and a [Points] field that runs from 1 to 50 and then back down from 50 to 1. We also have a [Side] field with values of Min or Max. The Min records will be used to draw the left side of our petals. The Max records will be used to draw the right side of our petals. And then we have a [Type] field to identify that these records are for our petals. Now we just need to join this table to our data source on the [Type] Field.

Building Your Circles


If you have read through Part 1 of the Fun With Curves series, then you may remember that in order to draw a circle in Tableau, we only need 2 inputs; the distance of each point from the center of the circle (the radius), and the position of each point around the circles (represented as a percentage).


Let’s start with the first input, the radius. We are going to size our circles based on the Value field in the Source Data. We want the area of our circles to represent the value in the data. So we have the area of each circle, we just need to use those values to calculate the radius of each circle. We can do this with the simple calculation below.


Radius = SQRT([Value]/PI())


Next, we need to calculate the position of each point around the circle. I’m not going to go into too much detail on this, but you can read more about it in the post mentioned above. To calculate this, we need the maximum number of points for our Circles (50), and we need the [Points] field (values 1 thru 50). For the max point calculation I am going to use an LOD because the max number of points for our circles, may not always align with the max number of points in our data source (but in this case it does).


Max_Point = {FIXED [PolygonType] : MAX([Points])}


Circle_Position = ([Points]-1)/([Max_Point]-1)


Next, we just need to plug the [Radius] and the [Circle_Position] values into our X and Y formulas for plotting points around a circle.


Circle_X = [Radius]* SIN(2*PI() * [Circle_Position])


Circle_Y = [Radius]* COS(2*PI() * [Circle_Position])


Now, let’s draw our circles

  • Right click on [Circle_X] and drag it to columns. When prompted, choose [Circle_X] without any aggregation

  • Right click on [Circle_Y] and drag it to rows. When prompted, choose [Circle_Y] without any aggregation

  • Right click on [Base_ID], change it to a Dimension, and drag it to Detail

  • Right click on [Order], change it to a Dimension, and drag it to Path

  • Drag [Type] to Filter Shelf and filter to ‘Circle’

  • Change the Mark Type to Polygon

Now you should have something that looks like this

Although it looks like one big circle, we actually have all 12 circles in this view. They’re just stacked on top of each other. So next we need to space these out a little bit. There are a lot of different techniques to do this, but here’s one I like to use to create Trellis Charts. This technique works great when you have a sequential ID field, which we do (Base_ID).

First, we’re going to create a numeric parameter that will allow us to choose the number of columns we want to create. We’ll call the parameter [Column Count] and set the value to 3. Next, we’re goin to use the [Base_ID] field to break our circles into columns and rows, starting with row.


Row = CEILING([Base ID]/[Column Count])


Column = [Base ID]-(([Row]-1)*[Column Count])


Now right click on both of these fields, change them to Dimensions, and then drag them to the appropriate shelf (Row to Rows, Column to Columns). The result should look something like this.

Building Your Petals


Alright, so this part is a little more complicated. I’m going to start by reviewing the basics of how you build these shapes, but I’m going to skim over the calculations since those will change significantly once we try to build these petals around our circle. No need to follow along with the workbook during this section.


So here are the basics. Let’s start by drawing a Bezier Curve with 4 control points. Our line is going to start at 0,0 and end at 5,10. Wow, this is easy, we already have the coordinates for 2 of the points!

Let’s take a look at our inputs. Our line will have a height of 10 and a width of 5. I’ve also built 2 parameters that we’ll use to calculate the 2nd and 3rd set of points. You can experiment with different values here, but these seem to work pretty well. We need a total of 8 values (4 sets of X and Y).

  • Point 1 will be the start of the line. In this case, it’s 0,0

  • Point 2 will appear on the same X axis as Point 1, but will be somewhere between the start and end of the line on the Y axis. I like to place it two thirds of the way, or .67 (the value in the P2 Parameter Input above). So the coordinates for Point 2 will be 0 and 6.7 (P2 Parameter x Height of the line)

  • Point 3 will appear on the same X axis as Point 4, and will appear somewhere between the start and end of the line on the Y axis (similar to P2). I like to place it halfway, or .5 (the value in the P3 Parameter Input above). So the coordinates for Point 3 will be 5 and 5 (P3 Parameter x Height of the line).

  • Point 4 will be the end of the line. In this case, it’s 5,10

If you were to plot these 4 points, you would have a jagged line like you see in the image above. But look what happens when we plug those values into our Bezier calculations


X = (1-[T])^3*[P1_X] + 3*(1-[T])^2*[T]*[P2_X] + 3*(1-[T])*[T]^2*[P3_X] + [T]^3*[P4_X]

Y = (1-[T])^3*[P1_Y] + 3*(1-[T])^2*[T]*[P2_Y] + 3*(1-[T])*[T]^2*[P3_Y] + [T]^3*[P4_Y]

Alright, we are halfway there! Kind of. So now we have a line that will create 1/2 of one of our petals. But in order to turn this into a petal shaped polygon, we need another line that’s a mirror image of this one.

This is where the Min and Max records come in. We need to calculate our 4 sets of coordinates for both sides. Luckily, most of the values are actually the same. P3 and P4 are going to be identical for both lines. And the Y values for P1 and P2 are the same. The only differences are the X values for P1 and P2. And to calculate those we just add the width of the whole petal (width x2) to our starting point. And if we were to plug these coordinates into the same calculations, we have this.

Now this is where the [Order] field comes into play. To make this one single polygon instead of two separate lines, we can use the [Order] field on Path and change the Mark Type to polygon

On the Left (Min) side, we have points 1 thru 50, running from the bottom left up to the top middle. On the right (Max) side, we have points 1 thru 50 running from the bottom right up to the top middle. But then we have the [Order] field (on label in the image above). This field runs from the bottom left to the top middle to the bottom right, in one continuous flow, from value 1 to 100. This is what makes it a single continuous polygon.

Ok, so that’s how we would build 1 single petal shaped polygon, perfectly positioned facing directly upward. But that’s not what we’re trying to do. We’re trying to build a dynamic number of petals, evenly spread around a circle and facing outward in the appropriate directions. So let’s do that.


Building Your Petals (for real this time)

We’re going to use a similar approach to what was described above, but everything needs to be plotted around a circle. So any calculations we use to determine our 4 points are going to have to run through those X and Y calculations for plotting points around a circle. That means, for all of our points, P1 thru P4 for both sides, we need to calculate two things; the distance from the center of the circle, and the position around the circle. But before we calculate those specific points there are a few other calculations that we’ll need. We also need a parameter, called [Petal Count] that will allow us to select how many petals we want. This should be a numeric parameter, and let’s set the value to 10 (I recommend using a range, allowing values from 4 to 24)


T = ([Points]-1)/([Max_Point]-1) – this is the same as the [Position] calc used earlier. It’s used to evenly space points between 0% and 100%


Petal_Count_Filter = [Polygon ID]<=[Petal Count] – this will be used as a filter to limit the number of petals displayed to what is selected in the [Petal Count ] parameter


Petal_Width = 1/[Petal Count] – this calculates the total position around the circle that will be occupied by each petal. For example, if there were 10 petals, each one would occupy 1/10 of the space around the circle, or .10


Petal_Side_Position = IF [Side]=’MIN’ THEN ([Polygon ID]-1)*[Petal_Width] ELSE [Polygon ID]*[Petal_Width] END – this calculates the position of the start of each Min line and Max line. If there were 10 petals, the Min side of the 2nd petal would be at position .1 or (2-1)*.1, and the Max side of the petal would be at position .2, or 2*.1. The Min value will share the same position as the Max value of the previous petal. The max value will share the same position as the Min value of the next petal


Petal_Middle_Position = ([Polygon ID]/[Petal Count]) – ([Petal_Width]/2) – this calculates the position of the center of each petal. If there were 10 petals, the center of petal 3 would be at .25, or (3/10) – (.1/2). This is also halfway between the position of the Min line and the Max line.


Alright, now we can calculate all of our coordinates. Let’s start with P1. For the first input, we want this point to start right at the edge of our circle. So the distance from the center is going to be equal to the radius of the inner circle. So the first input is just [Radius]. For the second input, we’ll use the the [Petal_Side_Position] we calculated above.


P1_X = [Radius]* SIN(2*PI() * [Petal_Side_Position])

P1_Y = [Radius]* COS(2*PI() * [Petal_Side_Position])


If we were to plot these points for 12 petals, we would end up with 24 points, but it would appear that we only 12 because each is overlapping with another point. But this gives us the outside edges of each of our petals

Now onto P2. This one is a little more complicated. We’re going to use P1 as a starting point for this calculation, instead of the center of the inner circle. Now we need to calculate the distance from P1 where we want our next point to appear. First, we need to determine the length of the entire petal. I like to use a parameter for this so I can dynamically adjust the look of the flowers. So let’s create a parameter called [Petal_Length_Ratio]. This is going to be a number relative to the radius, so a ratio of 1 would set the length of the petal equal to the radius of the circle. A value of .8 would set the length of the petal equal to 80% of the radius, and so on. I usually go with a value somewhere between .5 and 1. We’ll use this along with the radius, so that the petals of each flower are sized appropriately based on the size of their inner circle. Next, we need to position this point somewhere between the start of the line and the end of the line. As I mentioned earlier, I like to place it two thirds of the way (P2_Parameter from the previous section). So the first input, the distance from P1, is going to be the radius x the length ratio x the P2 parameter. For the second input, we’re going to use the [Petal_Middle_Position] because we want this side of the line to follow the same path as the line with P3 and P4. If we were to use the [Petal_Side_Position] field, we would end up with really wide, strange looking petals. This will probably make more sense a little further along. For now, let’s plug those values into our X and Y calcs.


P2_X = [P1_X] + (([Radius] * [Petal_Length_Ratio] * [P2_Parameter]))* SIN(2*PI() * [Petal_Middle_Position])


P2_Y = [P1_Y] + (([Radius] * [Petal_Length_Ratio] * [P2_Parameter]))* COS(2*PI() * [Petal_Middle_Position])

P3 is a little more straight forward. For the first input, we’re going to calculate the distance from the center of the inner circle. And then we’ll use a similar approach to what we did for P2. The first input will be the radius + (the radius x the length ratio x the P3 parameter). As I mentioned in the earlier section, I like to set this parameter to .5. And once again, we’re going to use the [Petal_Middle_Position] field for the second input.


P3_X = ([Radius]+([Radius] *[Petal_Length_Ratio] * [P3_Parameter]))* SIN(2*PI() * [Petal_Middle_Position])


P3_Y = ([Radius]+([Radius] *[Petal_Length_Ratio] * [P3_Parameter]))* COS(2*PI() * [Petal_Middle_Position])


P4 is almost identical to P3, except we don’t need the length ratio. We want this point to appear at the end of the line. So we can just remove that from the calc.


P4_X = ([Radius]+([Radius] * [Petal_Length_Ratio])) SIN(2*PI() * [Petal_Middle_Position])

P4_Y = ([Radius]+([Radius] * [Petal_Length_Ratio])) COS(2*PI() * [Petal_Middle_Position])


We’re almost there! If we were to plot these points for the first petal in our lotus flower, it would look like this. It looks very similar to what we reviewed in the previous section, but with one very important difference…everything is at an angle…which is what we wanted.

All that’s left to do is to plug all of these points in our Bezier calcs and then build our polygons!


Petal_X = (1-[T])^3*[P1_X] + 3*(1-[T])^2*[T]*[P2_X] + 3*(1-[T])*[T]^2*[P3_X] + [T]^3*[P4_X]


Petal_Y = (1-[T])^3*[P1_Y] + 3*(1-[T])^2*[T]*[P2_Y] + 3*(1-[T])*[T]^2*[P3_Y] + [T]^3*[P4_Y]


Now the polygons. Let’s build this as a Trellis chart, just like we did with the Circles. So drag [Row] on to Rows and [Column] onto Columns. And then;

  • Right click on [Petal_X] and drag to Columns. When prompted, select [Petal_X] without aggregation

  • Right click on [Petal_Y] and drag to Rows. When prompted, select [Petal_Y] without aggregation

  • Drag [Type] to Filter Shelf and filter to ‘Petal’

  • Drag [Petal_Count_Filter] to Filter Shelf and filter to TRUE. Right click and ‘Add to Context’

  • Drag [Polygon_ID] to Detail

  • Drag [Order] to Path

  • Change Mark Type to Polygon

We’re so close! Your sheet should look like this:

The only thing left to do is to combine the Circle polygons with the Petal Polygons. We have separate data for them, all we need to do is get them on the same sheet. So we’ll create two more simple calcs to bring it all together.


Final_X = IF [Type]=’Circle’ THEN [Circle_X] ELSE [Petal_X] END


Final_Y = IF [Type]=’Circle’ THEN [Circle_Y] ELSE [Petal_Y] END


Now just replace [Petal_X] and [Petal_Y] with [Final_X] and [Final_Y] and drag [Type] from the filter shelf on to Color and you should have your lotus flowers!

The Final Touches


The hard part is done, now to make it look pretty. Play around with some of the parameters until you get the look that you like. Adjust the [Petal Count], the [Column_Count], the [Petal_Length_Ratio], and even the [P2_Parameter] and [P3_Parameter] if you wanna get crazy.


Next, throw some color on there. You could make the color meaningful to encode some data, or you could do what I just did and color it randomly. I used the calc below and then just assigned one of the color palettes I have saved.


Color = [Type] + STR([Base ID])

And that’s it! If you made it this far, please reach out and let me know what you thought, and what you came up with. Thank you so much for reading, and keep an eye on the blog for more ‘Totally Useless Charts & How to Build Them’

bottom of page