In BIRT is it possible to create a chart from summarized data columns? - charts

Is it possible to create a line chart using summarized data from dataset?
My scenario is the following:
detail section: each one of the cells are one output field in the dataset
JAN FEB MAR
item1 R X R
item2 X A R
item3 R R R
footer section: here we count the occurrence of each value per month by using count aggregation elements and filter by value
TOTALS:
R 2 1 3
X 1 1 0
A 0 1 0
And what I need to do is to add a chart that shows something like this:
Needed Chart
And what I have is this:
report output
report design
In EXCEL this is really simple, but I cannot figure out how it can be done in BIRT.
I thought something like to create a new data set with 3 output fields for R, X, and A and each row will be one month, so I will have a transposed table and that way it will me much easier for graph it. But I cannot do it using the aggregation fields, and I cannot find out how to it with the output fields from the main dataset.
Any ideas? If you need the source rptdesign file I can provide it to you, but the logic in it could be hard to understand.
Any help is appreciated, and thanks in advance.
Have a great 2020.

First of all, a BIRT rule of thumb: if you need aggregations outside of a table, create them outside of a table. Do not try to access values in a table from the outside. It is possible, it may sometimes be the only solution, but it usually messes up your whole report, it is hard to debug, and even harder to maintain.
Aggregate
As your dataset looks quite simple and you already know how and what to aggregate, your first call should be computed columns in the dataset:
Here you aggregate in the language according to your datasource. If that is SQL, I guess a COUNT and GROUP BY statement will do the job.
Create all the columns you need for your graph here.
BTW: Computed columns are usually the silver bullet in BIRT. I use them for almost any pre-computation or custom field creation.
Visualize
You did not mention the library you are using for graphs, so I will assume you want to use the basic BIRT graphs. The basic charts with the months on the x-axis will do your job. I just want to add here that you have two options for multiple series:
You can either prepare your dataset so that you can feed the graph with a series per type (one line in your chart example) OR maybe easier: use optional y series grouping on your computed columns (as mentioned):
This way your graph will create the separate series for you. I hope this helps!
If you get stuck with the basic birt grpahs in general, you might want to think about finding a JavaScript-based graph library that does exactly what you need and implement that. Remember: you can put almost anything that is based on JavaScript into BIRT.
Final remark: For the sake of your report end users, please use a multi-bar chart. Line charts are not readable for overlapping values.

Thanks Kekzpanda for your help and time helping me in this question I had.
After struggling for a while I finally reach for a solution transposing the "table" of aggregations I had in the table footer, by using javascript arrays and an extra dataset and here are the steps I did in case someone else have the same problem:
For example, you need to transpose a table of 10 columns and 3 records
In report initialize method create an array with [10,3] dimension
// bi dimensional array indexes
var i=0;
var j=0;
// array definition and initialize it using 'for' iteration
var matriz = new Array(10);
for (i=0;i<10;i++){
matriz[i] = new Array(3);
}
// restart the array indexes in case you need to go through it in the future
i=0;
j=0;
Then you need to save the aggregation field value in one of the positions in the array. For that click on the aggregation field and go to the onCreate method and add the following code:
matriz[0][1]=this.getValue();
When finish all the aggregation fields, you will have an array with the transpose table. CHECKED!
Move the data in the array to the new dataset, select the fetch method and add something like this:
if(i >= array.length) return(false); // when you finish going through each item in the array.
row["A"]=matriz[i][0];
row["B"]=matriz[i][1];
row["C"]=matriz[i][2];
i++; // increment the first index by 1 to move to next row in the array
return (true);
Now you have your new data set with the transpose data.
Now work with this data set and graph the data, create the different series in the graph design for each column in the dataset.
Hope this help.
Bye.

Related

Spotfire - Filtering a Table by Values in a Calculated Column

I am trying to filter a table visualization of all of my data by looking to see if a Study Number contains Activity A. If a Study Number contains Activity A then I want to filter for all rows containing those Study Numbers even if the Activity is not A. See mock data below. In my real data set I have ~55,000 rows.
I have created a calculated to return Study Numbers if Activity= A but I am not sure where to go from there. Thanks for any help.
If(UniqueConcatenate([Activity]) OVER ([Study Number])~="A","Y","N")
Will give you this resulting column that you can then filter on (or you can use the formula as a Data Limiting Expression:

Count the number of instances of values across multiple dimensions in Tableau

I'm currently looking to count the number of instances a values shared across multiple dimensions. For example, say I have the following set of data:
And I want to return something like:
But ideally in the form of a bar graph. I want to keep the names associated with the data, so I can filter lets say by all "Bobs" or all "Hannahs".
Does anyone have any advice on how to do this in Tableau?
Here are a couple of ways you may be able to do this.
1) Create a calculated field for each food type. This is a bit cumbersome and you would need to add new ones for any new foods added. You calculations would look like this:
Hamburgers:
SUM(IF [Food1] = 'Hamburgers' OR [Food2] = 'Hamburgers' THEN 1 END)
Then you would make use of the Measure Names and Measure Values built-in fields.
2) You can normalize your data. If you are referencing a Excel or Text file, you can do this right in Tableau. Simply go to the Data Source tab, select the Food fields, and choose to Pivot them:
Goes to:
Now you can do:
Finally, both results support creating a bar chart:

Apply matlab function to large table grouped by variables

I have a large table in Matlab of 7 variables and about 2 million rows. The first columns/variable has Ids, the second has dates, and the 3rd variable has prices. For each Id and each date I want to check whether the price was above 100 in each of the previous 6 days. I have a solution but it's very slow, so I would like ideas for improving speed. My solution is the following (with some toy data):
Data = table(reshape(repmat(1:4,3000,1),12000,1),repmat(datestr(datenum(2001,01,31):1:datenum(2009,04,18)),4,1),normrnd(200,120,12000,1),...
'VariableNames',{'ID','Date','Price'});
function y=Lag6days(x)
y=zeros(size(x));
for i=7:size(x,1)
y(i,1)=sum(x(i-6:i-1,1)>100)==6;
end
end
Func = #Lag6days;
A = varfun(Func,Data,'GroupingVariables',{'ID'},'InputVariables','Price');
Any suggestions?
This might have something to do with the table data structure - which I'm not really used to.
Consider the use of 'OutputFormat','cell', in the call of varfun, this seems to work for me.
Of course you would have to make sure that the grouping procedure of varfun is stable, so that your dates don't get mixed.
You could consider extracting each ID group into separate vectors by using:
A1 = Lag6days(Data.Price(Data.ID==1));
...
So you can have more control over your dates getting shuffled.
PS: Obviously your algorithm will only work if your prices are already sorted by date and there's exactly one price entry per day. It would be good practice to check for these assertions.

Tableau table hides categories with no data - how to prevent?

I have Tableau report where I am showing data by category in columns.
The table shows all columns when there is no filter on data. But when filter is applied, some of the categories do not have data, so table shrinks, hiding columns without data
Is there a way to always show columns regardless of data or not in that column?
Please see screenshots below.
Go to Analysis >Table layout> Show columns with no data or
Analysis>Table layout>Show rows with no data
The next step depends on whether your "disappearing" fields are dimensions or measures.
If you want to force the display of members for specific dimensions, then one (kind of complex) solution is to use an advanced Tableau feature called data blending to force the existence of dimension members, even if there are no related measure values. The trick is to make a simple data source, say a text file, that lists the members of each dimension. Use that source as the primary data source, and make the original data source the secondary source.
Go to Analysis >Table layout> Show columns with no data or Analysis>Table layout>Show rows with no data
Also You can right click on header and select show missing values if you are using line chart.
Solution 1: (When you’re working with Dates or Numeric bins)
Right click on the numerical or Date column to extrapolate the missing values. As you notice in the lower part of the screenshot, this will not work on Categorical data !
Solution 2: Categorical Data
As indicated in the accepted answer, Analysis > Table Layout > Show Empty Rows will get you the same result for Categorical (Text) Data
Solution 3: Calculated Columns
If for some reason, none of the 2 above point & click solutions work, you can create calculated columns to calculate the measure for each of the Categories with the below formula and then line them up on the Columns to achieve the same result
Profit (Category 1)
IF MyColumn = "Category 1" THEN
Profit
ELSE
NULL
END
Profit (Category 2)
IF MyColumn = "Category 2" THEN
Profit
ELSE
NULL
END
Not the most convenient solution when you have hundreds of unique values in your column, but nevertheless a workaround !

Working with a delimited list of items in a Tableau field

I am preparing a data visualization in Tableau.
I have some data that can be simplified like this:
Name, Score, Tag
Joe, 5, A;B
Phil, 7, D
Quinn, 9, A;C
Bill, 3, A;B;C
I would like to generate a word cloud on the Tag field that counts
occurances of each item A,B,C. So I need to generate this:
A,3
B,2
C,2
D,1
In other words, I need help working with a field that contains a list of delimited values.
In the example data ; is the delimiter, but it could be anything.
I would like the word cloud to update as the user
applies filters, e.g. dragging a slider to set score > 5.
So the tag count has to be done on the fly.
I'm pretty sure I'll need to use field calculations and table calculations..?
Possibly I'll need to have a separate table tracking the tags..?
I have no problem building the word cloud and other viz elements.
What I'm looking for help with is parsing the delimited list field and
calculating the tag counts.
I do have full control over the source data, so if there is an easier way to
do this by reorganizing the schema, I'd be glad to do that. I thought of breaking
the field up into spearate tag1, tag2, tagX fields and trying to count over the
separate fields... but not sure if this is any simpler.
Thanks for any tips.
Another (probably better in your case) approach is to reshape the data before feeding it to Tableau. Tableau works best with normalized data.
Preprocess it to look like:
Name, Score, Tag
Joe, 5, A
Joe, 5, B
Phil, 7, D
Quinn, 9, A
Quinn, 9, C
Bill, 3, A
Bill, 3, B
Bill, 3, C
At that point, the standard Tableau word cloud charts should work well, and it will scale easily as you add more tags and data.
Reshaping data to normalize it prior to analysis with Tableau is a pretty standard step. Sometimes you can do it automatically, say with custom SQL, but often you'll have to use some sort of script first. If your data comes from Excel, Tableau has a plug in that can help with reshaping data. Look for it on the Tableau knowledge base.
Here's an approach that would be tolerable if you had a fixed set of 3 or 4 tags. Since you have closer to 50K possible tags, it's not a feasible approach for your problem as is. But maybe it will give you an idea. Similar approaches can be used to solve different kinds of problems in Tableau, so its a useful trick to know.
For each tag, create a boolean calculated field that returns 1 if the current row contains that particular tag and null otherwise (or whatever the condition is you want to detail)
For example, define a calculated field called Tag_A defined as:
if contains(Tag, "A") then
1
end
Similar, define calculated fields Tag_B, Tag_C etc
So far it's easy.
Then you can use those fields in other calculations to count the number of records that contain tag A, filter to only those that contain A, use the calculated field on the condition tab when defining sets that are computed dynamically by a formula ... Of course, the low level calculated field function can be more complex, say checking for the presence of at least 2 fields out of a list for example.
If nothing else, this approach sometimes lets you break complex problems into bite sized pieces.
Unfortunately, hard coding calculated field names won't scale to 50K tags. For that, you probably want to reshape your data.