Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I love Mathematica, and I would love to be able to use it for all of my data analysis tasks, but there is one type of analysis which I find almost trivial in R, and I have no idea how to approach in Mathematica.

Say I have a CSV file containing a few hundred thousand people's ranked preferences for items, in a format like this:

Gender,X29234,X30310,X28908,...
Male,1,2,3,...
Female,1,3,2,...
...

(in this case the female liked item X28908 more than item X30310)

10000 rows of sample data can be found here.

I want to plot histograms of the ranks each gender assigned to each item. In R I can use reshape2 and ggplot2 to do something like this:

library(reshape2)
library(ggplot2)
merged_data <- read.csv("merged_data.csv")
melted = melt(merged_data, id=1)
ggplot(melted)
 + geom_histogram(aes(x=value,y = ..density..,fill=factor(Gender)),binwidth=1, position="identity",alpha=.5)
 + facet_wrap(~variable)
 + theme(legend.position="bottom")
 + scale_fill_discrete(name="Gender: ")

to get a nice graph like this:

histograms

The key thing for me here are that the individual plots all end up having the same axis bounds, even though the bounds of the data in each plot aren't the same, which makes comparisons really easy.

How would I go about doing something like this in Mathematica so I can get rid of R in my workflow?

Edit: I should clarify that this example with Gender is to simplify the problem to something easier to explain, and I'm looking for a solution which is as automatic as possible: doesn't involve enumerating in the source the possible values of the Gender field, doesn't involve hard-coding in the source the bounds of the plot etc. ggplot2 does all of these out of the box, so I'm looking for a reusable approach to do something similar.

share|improve this question
2  
Could you add some sample data (for example, merged_data.csv) that you used for the R plot (or link to it somewhere)? –  rm -rf Nov 2 '12 at 3:05
    
Coming right up... –  nicolaskruchten Nov 2 '12 at 3:14
    
Edited to add pastebin link to 10k lines of sample data –  nicolaskruchten Nov 2 '12 at 3:20
    
@nicolaskruchten, have you tried setting PlotRange to the same value for all graphs? –  alancalvitti Nov 2 '12 at 3:38
    
To be honest, I don't even know to split the data in this way and generate all these graphs in the first place, or how I would compute the PlotRange to assign to them :) –  nicolaskruchten Nov 2 '12 at 3:52
add comment

2 Answers

up vote 10 down vote accepted

If I understand correctly, this question is about complete automation for uniform look. Hence the specifics of solution below. Import data:

data = Import["http://pastebin.com/download.php?i=fZKMqxK9"];

Define filter that automatically separates data by gender:

filter[gender_] := Rest[Transpose[Select[data, #[[1]] == gender &]]]

For complete automation find absolute domain and range for all plots so it is easy to compare them (not sure if this is most elegant way):

doMraN = {{1, Max[Rest@Transpose@Rest@data]},
          {0, Max[((Max[#]/Total[#]) &@Tally[#][[All, 2]]) & /@ 
              Flatten[(filter /@ Union[Rest[data[[All, 1]]]]), 1]]}}

{{1, 14}, {0, 977/1411}}

And you are done basically:

MapThread[Histogram[{#2, #3}, Automatic, "Probability", PlotRange -> doMraN, 
 PlotLabel -> #1[[1]], ChartStyle -> 54, GridLines -> {None, Automatic}, Frame -> True] &, 
 filter /@ Prepend[Union[Rest[data[[All, 1]]]], "Gender"]]

enter image description here

Grid[data[[1 ;; 20]], Frame -> All, Alignment -> Left, Background -> {{Yellow}, {Green}}]

enter image description here

share|improve this answer
    
Wow, that's impressive! Is there any way to avoid hardcoding the "Male" and "Female" strings and have it break out according to all the unique values of a column (i.e. so that if I added rows with an "Unknown" gender a third set of bars would automatically appear)? –  nicolaskruchten Nov 2 '12 at 4:45
    
@nicolaskruchten Yes, it is possible to automate the filtering of genders, - please see updated code. –  Vitaliy Kaurov Nov 2 '12 at 5:09
    
OK, very neat. The only remaining issue is the bounds of the plot: I see that you hard-coded the range, and that the domain is left to chance, for example the second plot only goes to 10. Would I have to generate the list of plots, iterate through them to find the min/max of the domain/range and then apply that to each plot? –  nicolaskruchten Nov 2 '12 at 5:24
    
@nicolaskruchten Done, see update. But I am sure there are many other ways to find domain/range - maybe more elegant ones. –  Vitaliy Kaurov Nov 2 '12 at 5:56
    
Thanks very much! I've learned a lot from this answer :) –  nicolaskruchten Nov 2 '12 at 12:15
add comment

Well, the following will get you close ...

    idata = Import["merged_data.txt", "CSV"];
    Dimensions@idata
    hedr = idata[[1]];
    idata = Rest@idata[[2 ;;]];
    ftik = {#, #/10000.} & /@ Range[0, 6000, 1000];
    xtik = {#, #} & /@ Range[0, 15, 1];
    hlist = Histogram[{
          Select[idata, SameQ[#[[1]], "Female"] &][[All, #]],
          Select[idata, SameQ[#[[1]], "Male"] &][[All, #]]}, {1},
         PlotLabel -> hedr[[#]],
         Frame -> True,
         GridLines -> Automatic,
         FrameTicks -> {{ftik, None}, {xtik, None}},
         PlotRange -> {{0, 15}, {0, 6000}},
         ImageSize -> 200,
         BaseStyle -> {FontFamily -> "Helvetica", FontSize -> 12}
         ] & /@ Range[2, Length@hedr];
    GraphicsGrid[
     Join[Partition[hlist, 4], {{hlist[[12]], hlist[[13]], hlist[[14]]}}]]

How much closer to you need to get?

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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