4
$\begingroup$

I'm currently experimenting using the Titanic example data set:

titanic = ExampleData[{"Dataset", "Titanic"}]

I'm able to extract a specific column and then chart, for example, a histogram for it:

titanic[Histogram, "age"]

However, the trouble started when I wanted to construct a DistributionChart for two of these columns, say age and class:

titanic[DistributionChart, {"class","age"}]

This produces as many chart elements as there are observations. I just want the chart to have two elements: one for "class" and one for "age".

How can I achieve this?

$\endgroup$
  • 1
    $\begingroup$ I think the problem is that the values in question are not the same for "age" and "class". For the same reason you could not combine histograms for "temperature" and "cost", or "length" and "weight"... $\endgroup$ – David G. Stork Feb 15 '17 at 19:35
2
$\begingroup$

I think the problem is that the values in question are not the same for "age" and "class". For the same reason you could not combine histograms for "temperature" and "cost", or "length" and "weight".

You can of course make two histograms that have the same attribute, for instance only "age" or only "weight" or only "length" as here:

data1 = RandomInteger[{1, 20}, 200];
data2 = RandomInteger[{10, 30}, 400];
Histogram[{data1, data2}]

But in your case you must make two separate graphs (because you cannot plot the class "1st", "2nd", "3rd" on the same axis as the age 10, 11, 12, ...):

titanic[Histogram, "age"]

or

BarChart[Counts[Sort[titanic[[All, 2]]]]]

and

BarChart[Counts[titanic[[All, 1]]]]
$\endgroup$
  • $\begingroup$ Ok, so it should work if I had let's say two columns both indicating age? $\endgroup$ – EBassal Feb 15 '17 at 20:00
6
$\begingroup$

There are a couple of problems to overcome to get this to work: the data needs to be transposed, and class is not numeric.

Problem #1: the data needs to be transposed

The subquery {"class","age"} produces a pair of elements (strictly: an association with two elements). Thus, we end up presenting Histogram or DistributionChart with a list of pairs. But to get the desired result, we must instead supply two lists of individual values.

We can accomplish this by transposing the data before plotting it:

titanic[Transpose /* DistributionChart, {"class", "age"}]

dataset screenshot

Hmmm, the class distribution is blank. This just brings us to the second problem...

Problem #2: class is not numeric

The class values in the Titanic dataset are not numeric and so will be ignored by DistributionChart. That is why we only see one distribution, for age.

For illustration purposes, we will create a second dataset that adds another numeric column containing the age skewed by a random offset:

titanic2 = titanic[All, <| #, "skewedAge" -> #age + RandomInteger[{-10, 10}] |> &]

Now, we can see how transposition solves the first problem:

titanic2[Transpose /* DistributionChart, {"age", "skewedAge"}]

dataset screenshot

This works for Histogram as well:

titanic2[Transpose /* Histogram, {"age", "skewedAge"}]

dataset screenshot

Alternate Approach

As an alternative to using Transpose, sometimes we can apply query operators at a higher level to produce two independent lists of values instead of one list of pairs. For example, we could use GroupBy to split the Titanic dataset into groups based upon sex, and then plot the resulting values:

titanic[GroupBy["sex"] /* DistributionChart, All, "age"]

dataset screenshot

Labels would probably be useful here:

titanic[GroupBy["sex"] /* (DistributionChart[#, ChartLabels->Keys[#]]&), All, "age"]

dataset screenshot

$\endgroup$
1
$\begingroup$

I just want the chart to have two elements: one for "class" and one for "age".

Here is an alternative way to plot that relation using the package MosaicPlot.m:

Import["https://raw.githubusercontent.com/antononcube/MathematicaForPrediction/master/MosaicPlot.m"]

ageQF = Piecewise[{{1, -Infinity < ##1 <= 5}, 
   {2, 5 < ##1 <= 14}, {3, 14 < ##1 <= 21}, {4, 21 < ##1 <= 28}, 
   {5, 28 < ##1 <= 35}, {6, 35 < ##1 <= 50}, {7, 50 < ##1 <= Infinity}}, 0] &;

ageQFRules = {1 -> "1(under 6)", 2 -> "2(6...14)", 
   3 -> "3(15...21)", 4 -> "4(22...]28)", 
   5 -> "5(29...35)", 6 -> "6(36...50)", 
   7 -> "7(50+)", 0 -> "0(missing)"};

titanic2 = 
  titanic[All, 
          <|#, "qage" -> If[Head[#age] === Missing, 0, ageQF[#age]] /. ageQFRules|> &];

MosaicPlot[titanic2[All, {"class", "qage"}], 
 "LabelRotation" -> {1, 0.5}, ImageSize -> 600]

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.