# Plotting 2D Data with Categorical Data in One of the Dimensions

I have a 2D data set in the form of:

data={{Category, Integer}, {Category, Integer},{Category, Integer}...}


It is a pretty simple data set with four categories and several hundred rows. I am looking to make a scatterplot of the data resulting in a visualization with four columns of points, one for each category (placing categories on the X-Axis).

This should be a very easy plot to produce using:

ListPlot[data]


Mathematica returns a blank plot with no error messages. I have also tried using DistributionChart with the following code:

DistributionChart[data, ChartElementFunction -> "PointDensity"]


Do I need to transform the categorical values to numeric? If I run this in R, it can identify they categories and handle appropriately.

Update 1:

Here is an example of what I get from R. The data set is movie ratings. It is out of scope for this posting, but I also like the Jitter function in R (as seen in this image) which seems not to have an equivalent function in M9. I usually play with opacity when I have many overlapping data points.

Update 2:

Correct. The data is more accurately written as such:

data = { {{cat1, d11}, {cat2, d12}, {cat3, d13}, {cat4, d14}},  {{cat1, d21} ...}, ...}

-
Can you paste what you get from R so we can see what you might be trying to achieve in Mma? – Mike Honeychurch Feb 24 '13 at 1:21

Perhaps something like the following will work. First I generate 500 pairs with categorical x coordinate and integer y coordinates.

cat = {"Red", "Green", "Blue", "Yellow"};
rule = Thread[cat -> {20, 15, 35, 25}];
data = Table[{#, RandomVariate[PoissonDistribution[(# /. rule)]]} &[
i], {i, RandomChoice[cat, 500]}];


The following code will convert the categorical data to numeric values and then label the x-axis with the category labels. It allows you to use all of the options available to ListPlot.

catListPlot[x_, o : OptionsPattern[]] :=
Block[{c},
c = Transpose[{#, Range[Length[#]]}] &[DeleteDuplicates[x[[All, 1]]]];
ListPlot[x /. (Rule @@@ c), Ticks -> {Reverse /@ c, Automatic}, o]
]


Here I plot the data I generated setting the AxisOrigin for better alignment.

catListPlot[data, AxesOrigin -> {0, 0}]


Or alternatively you might try something like BoxWhiskerChart.

BoxWhiskerChart[#[[All, All, 2]], ChartLabels -> #[[All, 1, 1]]] &[
GatherBy[data, First]]


EDIT:

Lets say you really just want to use your R visualization in Mathematica. I don't really know what visualization you might be working with but the standard plot should suffice as a starting point.

First we need to activate RLink and install R.

<<RLink
InstallR[]


Now I picked up the following trick, which allows us to view R plot in M, from the Mathematica marketing pages here.

mathematicaRPlotWrapper = RFunction["function(filename, plotfun){
pdf(filename)
plotfun()
dev.off()
}"];

getRPlot[plotFun_RFunction] :=
With[{tempfile = FileNameJoin[{$TemporaryDirectory, "temp.pdf"}]}, If[FileExistsQ[tempfile], DeleteFile[tempfile]]; mathematicaRPlotWrapper[tempfile, plotFun]; If[! FileExistsQ[tempfile], Return[$Failed]];
Import[tempfile]];


Now lets set the x and y variables from our data.

RSet["x", data[[All, 1]]];
RSet["y", data[[All, 2]]];


And finally we plot it...

getRPlot[RFunction["function(){
plot(y~as.factor(x))
}"]]


I've played with this quite a lot. The really cool thing to try is working with R plots in Manipulate which allows for dynamic control over R visualizations!

-
Thank you for posting the R code. I love the RLink functionality, but have not had enough free time to sit down and properly get into it. – Nguyen Van Falk Feb 24 '13 at 17:30

You say you have 4 categories by several hundred rows, which made me think at first that the data should be in the form

data = { {{cat1, d11}, {cat2, d12}, {cat3, d13}, {cat4, d14}},  {{cat1, d21} ...}, ...}


but that's not how the question is written. If data is a flat list of pairs, then perhaps the categories cycle 1, 2, 3, 4, 1 etc. One can partition it:

data = Partition[data, 4]


to get it in the first form. The first solution below handles these cases, assuming the data is partitioned. Or maybe there is no pattern to how the categories appear in the list. That would require a different approach, which is given in the second solution.

First solution

For $n$ rows of four pairs:

categories = {"A", "B", "C", "D"};

data = Table[Thread[{categories, RandomInteger[{1, 100}, 4]}], {20}];

ListPlot[data /. categoryRules, PlotRange -> {{0.5, Length@categories + 0.5}, Automatic},
Ticks -> {Table[{i, categories[[i]]}, {i, Length@categories}], Automatic}]


or

DistributionChart[Transpose@Map[Last, data, {2}], ChartLabels -> categories]


Output:

Second solution

For a single list of pairs: When we Reap we only get the data values, so for ListPlot we have to add the first coordinate.

categorySow[{cat_, datum_}] := Sow[datum, cat];
addX[tag_, l_] := {tag /. categoryRules, #} & /@ l;

data = Table[{RandomChoice@categories, RandomInteger[{1, 100}]}, {100}];

ListPlot[Flatten[Reap[categorySow /@ data, categories, addX][[-1]], 1],
PlotRange -> {{0.5, 4.5}, Automatic},
Ticks -> {Table[{i, categories[[i]]}, {i, Length@categories}], Automatic}]


or

DistributionChart[Flatten[Reap[categorySow /@ data, categories][[-1]], 1],
ChartLabels -> categories]
`

Output:

-