0

I want to plot different view angles of 3D plots, each of which has a same set of data colored differently according to groups. But the following approach seems to only plot the last group of data instead of keeping the previous groups.

fig = plt.figure()
# group_id is a group-id map, eg {'A': 0, 'B': 1, ...}
for k, v in group_id.items():
    # data_id indicates id of each data
    subset_idx = data_id == v  # obtain idx of data belonging to group k
    d = data[subset_idx]  # get the data subset
    for i, angle in enumerate([45, 90, 135, 180]):
        ax = fig.add_subplot(1, 4, i + 1, projection='3d')
        ax.view_init(azim=angle)
        ax.scatter(d[:, 0], d[:, 1], d[:, 2], c=colors[v], label=k)

The example runs into a warning:

MatplotlibDeprecationWarning:
Adding an axes using the same arguments as a previous axes currently 
reuses the earlier instance.  In a future version, a new instance will 
always be created and returned.  Meanwhile, this warning can be 
suppressed, and the future behavior ensured, by passing a unique label 
to each axes instance.
  "Adding an axes using the same arguments as a previous axes "

which should not cause any serious problem. However, the outcome seems to plot only the last group of data (the last item in group_id), suggesting ax = fig.add_subplot might have created new axes which doesn't match the description in the warning. What is more confusing to me is that the exact same approach for 2d plot works (though it gives the same warning).

Francis
  • 6,416
  • 5
  • 24
  • 32
  • Try ading the axes before the loop and acces each one in the loop. `fig,axes=plt.subplots(nrows=nplots, ncols=1)` and then acces the axes from the loop. Some information about the warning (https://stackoverflow.com/questions/46933824/matplotlib-adding-an-axes-using-the-same-arguments-as-a-previous-axes) – TavoGLC Mar 14 '19 at 03:28
  • There is a reason for this warning. So best try to avoid it (as you notice, reusing a 3D axis isn't even possible), by taking `add_subplot` literally, meaning add a subplot once you need it, but don't misuse it for activating a previous subplot. – ImportanceOfBeingErnest Mar 14 '19 at 13:37

1 Answers1

0

You can create all 4 axis instances before the for loop using let's say a list comprehension and then plot to each subplot within the for loop using the index i. Your code is not a MCVE so I can't run it to test but this should work. If not, post a comment below.

fig = plt.figure()
angles = [45, 90, 135, 180]

axes = [fig.add_subplot(1, 4, i+1, projection='3d') for i in range(len(angles))]

for k, v in group_id.items():
    subset_idx = data_id == v  
    d = data[subset_idx]  
    for i, angle in enumerate(angles):
        axes[i].view_init(azim=angle)
        axes[i].scatter(d[:, 0], d[:, 1], d[:, 2], c=colors[v], label=k)
Sheldore
  • 37,862
  • 7
  • 57
  • 71
  • Thanks! It works. I like the way how list comprehension is used in this case. It can be easily extended to plot both 2D and 3D plots in one figure using two lists of axes. – Francis Mar 15 '19 at 05:44