Counting max boolean in Tableau using LOD - aggregate

I have some data that looks like the following, where the same Id is repeated in multiple rows, but different Victory values.
Id
Victory
1
FALSE
1
FALSE
1
TRUE
2
FALSE
2
FALSE
2
TRUE
3
FALSE
3
FALSE
3
FALSE
I am trying to count the number of Victory per Id, so if there is a row where Victory is TRUE, then it should be considered a victory.
I have attempted to use a basic calculated field, which I thought would do the trick. However, it counts victory as TRUE right, but victory FALSE includes any Id where FALSE is present.
In other words, the above data would count 3x FALSE, and 2x TRUE, using the following calculated field:
COUNT ( { FIXED [Id]: MAX([Victory]) } )
This is the visualization I get, where I would expect the count of FALSE to only be 1, but is 3.
I have tried numerous variations, but just cannot seem to get the desired results.
I am using Tableau 2020.4.
EDIT
I came across two different solutions to my problem, which I have attached screenshots of below. Note that Victory is replaced by WIN and Id is replaced by Row Id, but the example should be clear.
Solution 1
Solution 2

First, make sure you understand how COUNT([Some Column]) behaves. It doesn't return the number of records that have TRUE in some column, or 1 in some column. It returns the number of records where [Some Column] has a value, any value at all. In other words, it returns the number of records that have a NON-NULL value.
That's why you are getting a higher than expected result. You are expecting COUNT to somehow only count the records where Victory had a particular value, TRUE in your case. As far as COUNT() is concerned, TRUE and FALSE are equivalent. COUNT() only cares whether there is a value at all - as opposed to null.
With that important comment out of the way, I suggest not evening using COUNT() for this case. The expression SUM(INT([Victory]))
will tell you how many rows have the value True for the field Victory. That expression works because the type conversion function INT() converts TRUE to 1 and FALSE to 0.
You can either wrap that expression in an LOD calc if you must, or make a calculated field measure defined as INT([Victory]). Place that field on some shelf with the aggregation function defaulting to SUM(), and place ID on another shelf, and you'll have your answer.
Only use an LOD when you actually need to. You have more flexibility - and often better performance - without using an LOD calc.

Related

Tableau Mixed Data

I've been tasked to set up a Tableau worksheet of counts of data (ultimately to create percentages) where the contrived incoming data looks like the following.
id fruit
1 apple
1 orange
1 lemon
2 apple
2 orange
3 apple
3 orange
4 lemon
4 orange
The worksheet needs to look something like the following:
Count of ids
2 Lemons
2 No lemons
I've only been using Tableau for about 4 hours, so is this doable? Can anyone point me in the right direction?
The data is coming in from a SQL Server database in a format that I can control if that helps contribute towards a solution.
Alex's solution based on sets are very good for this scenario, but I would like to show that LODs can be more flexible if you need to extend your solution to include more categories.
for the current scenario, create a calculation with below formula and create text table using COUNTD(Id)
{FIXED [Id]:IF MAX([Fruit]='lemon') THEN 'Lemon' ELSE 'No Lemon' END}
Now for the extension part, you are considering below list where you want to count IDs with Lemon, Apple and others. Since no double counting of Ids are allowed, categorization will follow the order. (This kind of precedence will be a headache without LODs)
Now you can change your calculation as below:
{FIXED [Id]:IF MAX([Fruit]='lemon') THEN 'Lemon'
ELSEIF MAX([Fruit]='apple') THEN 'Apple'
ELSE 'No Lemon or Apple' END}
Now your visualization automatically changes to include the new category. This can be extended for any number of fruits.
This is a good use for a set.
In the data pane on the left sidebar, right click on the Id field and create a set named "Ids that contain at least one lemon" (or use a shorter less precise name)
In the set definition dialog panel, define the set by choosing "Use all" from the General tab, and then on the Condition tab, define the condition by the formula max([Fruit]="lemon")
There are many ways to think of a set, but the most abstract is just as a mathematical set of Ids that satisfy the condition. Remember each Id has many data rows, so the condition is a function of many data rows and uses the aggregation function MAX(). For booleans, True is treated as greater than False, so MAX() will return True if at least one of the data rows satifies the condition. By contrast, MIN() is True only if ALL (non-null) data rows satisfy the condition.
Once you have a set that separates your ids into Lemon scented Ids and others, then you can use that set in many ways - in calculated fields, in filters, in combination with other sets to make new sets, and of course on shelves to make visualizations.
To get a result like your question seeks, you could put your new set on the Row shelf, and put CNTD(ID) on the text shelf or columns shelf. Make sure you understand why you need count distinct (CNTD) instead of SUM([Number of Records]) here.
BTW, the LOD calculation { fixed [Id] : max([Fruit]="lemon") } is effectively the same solution.

Using COUNT in Tableau to count observations by group

Thanks in advance for any advice you can offer! I'm building a Tableau dashboard to explore housing affordability and school quality in different neighborhoods in my area. A user will select their occupation and see a graph of neighborhoods plotted based on school quality and housing affordability. To explore housing affordability, I'm using county level assessor data with the valuation of every property matched to neighborhoods.
The goal is to display the percentage of homes in an area that are affordable given the median occupational wages for the job a user selected. Right now, I'm trying to use a calculated field with COUNT([Parcels]<[Occupation])/COUNT([Parcels]), but I need to find a way to count the number of properties in each specific neighborhood below the cut off value.
Does anyone know of a way to count elements of a particular group in this way in Tableau?
I'm on a Mac, using Tableau Desktop, and doing the back end analysis work in R. Thank you!
You seem to misunderstand what the function COUNT() does. You are certainly not alone. Count() behaves in Tableau almost identically to how it does with SQL.
Count([some field]) returns the number of data rows where the value for [some field] is not null. It does not not return the number of rows where [some field] evaluates to true, or a positive number, or anything else.
If [some field] always has a non-null value, then Count([some field]) is the same as SUM([Number of Records]). If [some field] is always null, then Count([some field]) is zero. Count() is not like Excel's CountIf function.
If you want to count data rows that meet a condition, you could try COUNT(if [condition] then 1 end) Since the missing ELSE case defaults to null values, that expression will count rows where [condition] is true.
So one way to get the percentage of affordable homes is count(if [affordable] then 1 end) / count(1) assumes each Data row represents a home. Then format your field to display as a percentage. Another option is to learn to use quick table calcs
If you want to display the number of rows in a given visualized table you could also use SIZE()
Source, official docs:
https://help.tableau.com/current/pro/desktop/en-us/functions_functions_tablecalculation.htm#size

Tableau isNull then 0 calculated field

I have my tableau workbook and I'm currently counting by a field called ID - COUNT([Id]) - while this is great, on days with no activity my dashboard doesn't show ANYTHING and I want it to show zero if there was no activity - so I do I change this to count but also replace null with 0 (zero)?
First make sure you understand what Count([ID]) does. It returns the number records in the data source that have a non-null value in the column [ID].
Count() never evaluates to null. But if you have no rows at all in your data after filtering, then you'll get an empty result set -- i.e. view data will not have any summary data to show at all - whether null or zero.
Wrapping COUNT() in a call to ISNULL() or ZN() won't help in that case.
The solution is to make sure you have at least one data row per day, even if all other fields besides the date are null. Aggregation functions ignore nulls so padding your data like this should not disturb your results. The simplest way is to make a calendar table that has one row per day with nulls in most columns. Then use a Union to combine the calendar with your original data source. Then Count(ID) will return zero on days where there are no other records besides the calendar entry.
You can also get similar results using data blending, although with a bit more complexity.

Summing 2 Statements Tableau

In Tableau, what are the rules when it comes to adding 2 statements if you cannot put everything in 1? In the first part of the statement below, I am trying to pull all products besides 1 of them from a distributor, then in the part I am trying to pull all the units except from 2 of the distributors. However, as you can guess, the cells are blank when I drag the pill over.
Is it best practice to just create 2 calculated fields and add THOSE together?
(IF [Distributor] = "NDC"
AND [Product] <> "PE Single Use"
THEN ['15] END)
+
(IF [Distributor] <> "NDC"
AND [Distributor] <> "M&D"
THEN ['15] END)
Here are a few simple rules about calculations in Tableau (and generally in SQL also)
If you don't specify a value in some case, say by leaving off the else clause in an if statement, the expression evaluates to null in that case. That can be fine or a problem depending on what you want. Consider null to mean no-value, or not-applicable or missing-value depending on your situation.
Nulls propagate through other expressions. A null value + anything yields a null value. You can explicitly test for null if necessary, but it is often better to keep simple expressions that evaluate to null when any part is null.
Aggregation functions like SUM(), MIN(), AVG() etc silently ignore null values. So AVG(Salary) is really the average of all the rows that had a non-null value in the Salary field. You don't get any warning about this, it is understood. If you want to know how many rows have a non-null value for a field, you can use the COUNT() function to check.
In your expression above, the two IF conditions are never both true for the same record. So at least one of the two halves of your expression is null in each case, so the resulting entire expression is always null.
There are other rules to learn when using table calcs and LOD calcs, but these rules apply throughout.

Filter main group members based on subgroup content in reporting services

In reporting services 2008 I have a filter grouping problem.
I want to remove some of the entries in the main group based on certain combinations of subgroup value.
I can make an expression that shows true when a combination is within the group or the inverse, but if I apply this expression to the group it just returns false, hence all the groups are removed.
=IIF((Fields!Group2.Value Like "String1") AND (Fields!Group3.Value Like "String2"),
1,
IIF(Not(Fields!Group2.Value Like "String1"), 1, 0))
If the above is true for all members in group 2 and 3 for the group 1 member it should be shown, if one of the members in the group 2 and 3 returns false the entry in group 1 should be removed.
If I add the above expression to the group 1 filter it always return 1.
The problem is that whether the member in group one consists of 1,1,1,1 or 1,1,0,1 - it always returns 1 on the group one level.
What can I do?
It sounds like to you need to check the values one-by-one for a group, and if any one of them fails the test, to produce a false result. It may help you to use an expression like this one:
=count("your_group") <= sum(iif(Fields!your_field.Value = yourCondition, 1, 0), "your_group")
This takes the total number of rows in your groups, then compares to the sum of the number of times a row meets a condition you set. So if one row fails the test, the expression will return false. One of the important pieces of this expression is the "your_group" part - that is called specifying your scope and is important if you want to reference a different group or level in an expression. More details here. You may have to do a bit of work to make this fit for you.