The set-up: I was able to generate some data and I merged it all together into one big matrix (exported and uploaded over here for use in this problem: EDIT: removed). When you download the data I exported, the columns that shouldn't be numeric will be imported as such. You can convert the data using:

bDat = Table[{bDat[[i, 1]], bDat[[i, 2]], ToString[bDat[[i, 3]]], ToString[bDat[[i, 4]]], ToString[bDat[[i, 5]]], ToString[bDat[[i, 6]]], ToString[bDat[[i, 7]]]}, {i, Length@dTry}]

I'm sure there's a more elegant way to do that, but that's what I quickly typed up that worked. Otherwise the plotting won't work. Then, I convert it to a dataset object so I can label the columns as such:

BigDat = Dataset[bDat];
BigDat = BigDat[All, <|"x" -> 1, "y" -> 2, "actual cluster" -> 3, "k means" -> 4, 
"k medoids" -> 5, "spectral" -> 6, "agglomerate" -> 7|>];

As a note, all values except those in the "x" and "y" columns should be strings. Now I know if I use GatherBy I could use ListPlot and the data will be colored based on the column that I gathered the data by, like so:

ListPlot[BigDat[GroupBy[Key["actual cluster"]], All, {"x", "y"}]]

enter image description here

The the problem I am having is this: I would like to add plot markers to this plot, but I want the plot markers to be based off another column. For example, I want to color the data by the "actual cluster" column, and then I want to give each point a plot marker based off the "k means" column.

I thought maybe

PlotMarkers -> BigData[All,"k means"]


PlotMarkers -> BigDat[GroupBy[Key["k means"]], All, {"x", "y"}]

might work since it gives you the list of values in that column in the former or in the latter, clusters the data by that column, but it didn't work the way I expected. PlotMarkers - Automatic just coordinates the plot markers with the colors, which isn't what I am after either. I'm not very familiar at all about how to use dataset objects or plotting them, so I am having difficulty figuring out how to do this. Any help would be appreciated.

  • 1
    $\begingroup$ I downloaded your dataset, but your ListPlot command plots an empty chart for me. $\endgroup$ – Victor K. Apr 17 '20 at 2:08
  • $\begingroup$ I exported the data as a csv, so it appears all the columns that shouldn't be numeric, are. If you try the code I added to the question on the imported data, it will work, because using GatherBy and then trying to plot, it can't plot with numbers but instead seems to work fine with strings. $\endgroup$ – Illari Apr 17 '20 at 2:19
  • 1
    $\begingroup$ ok, thanks, I missed the earlier condition. After transforming with BigDat = BigDat[ All, {"actual cluster" -> ToString, "k means" -> ToString, "k medoids" -> ToString, "spectral" -> ToString, "agglomerate" -> ToString}], I get essentially the same plot. $\endgroup$ – Victor K. Apr 17 '20 at 2:28
  • 1
    $\begingroup$ Yep. I have a love/hate relationship with Dataset - it's super powerful, but with sometimes weird syntax and its own quirks. $\endgroup$ – Victor K. Apr 17 '20 at 2:31
  • 1
    $\begingroup$ Why did you delete the link to the data? $\endgroup$ – J. M.'s torpor Apr 17 '20 at 17:16
bd = Import[

dS = Dataset[MapAt[ToString, bd, {All, 3 ;;}]];

dS = dS[All, <|"x" -> 1, "y" -> 2, "actual cluster" -> 3, 
    "k means" -> 4, "k medoids" -> 5, "spectral" -> 6, "agglomerate" -> 7|>];

labeling[index_: 97, fsize_: 16] := Apply[ Labeled[{#, #2}, 
      Style[#3, FontSize -> fsize, FontColor -> (ColorData[index]@FromDigits@#4)], 
      Center] &, #, {-2}] &;

lpdata = dS[GroupBy["actual cluster"] /* labeling[], 
    All, {"x", "y", "k means", "actual cluster"}];

ListPlot[lpdata, BaseStyle -> AbsolutePointSize[0], 
   PlotLegends -> PointLegend[Automatic, "LegendMarkers" -> {"Bubble", 10}, 
     LegendLabel -> "actual cluster"], ImageSize -> Large]

enter image description here

  • $\begingroup$ Fantastic! Thank you so much, this was exactly what I was looking to do. $\endgroup$ – Illari Apr 17 '20 at 16:59
  • $\begingroup$ @Jony, my pleasure. Thank you for the accept. $\endgroup$ – kglr Apr 17 '20 at 17:00

Getting the data:

BigDat = Dataset[
BigDat = BigDat[
  All, <|"x" -> 1, "y" -> 2, "actual cluster" -> 3, "k means" -> 4, 
   "k medoids" -> 5, "spectral" -> 6, "agglomerate" -> 7|>];
BigDat = BigDat[
  All, {"actual cluster" -> ToString, "k means" -> ToString, 
   "k medoids" -> ToString, "spectral" -> ToString, 
   "agglomerate" -> ToString}];

I played with this problem a bit and found a solution, but it's not pretty. Basically, ListPlot doesn't allow colors and markers to differ. What you can do, though, is to plot several charts, each with its own plot marker, and combine them with Show:

 ListPlot[<|"1" -> {{1, 1}, {2, 2}}, "2" -> {{3, 3}, {4, 4}}|>, 
  PlotRange -> {{0, 7}, {0, 7}}, PlotMarkers -> "1"],
 ListPlot[<|"1" -> {{5, 5}}, "2" -> {{6, 6}, {7, 7}}|>, 
  PlotMarkers -> "2", PlotLegends -> None]]


enter image description here

Of course, you would also need to clean up the legend and do a bit of programming to generate the list of ListPlots automatically, but it's doable.

  • 1
    $\begingroup$ Yep, that's what I ended up doing too. I changed the plot marker sizes and colors and then overlaid them to get an approximation of what I wanted. It's frustrating that color and markers seem so intertwined like this! Thanks for having a go at it, though. Appreciated. $\endgroup$ – Illari Apr 17 '20 at 3:05

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.