First of all some style comments:
- Please use spaces after commas and around operators – It is hard to read your sequence of values for the
X
and y
lists when they are all compressed. And the same applies for the ([2,7])
when setting limits. It reads a lot better with [3, 3.2, 3.5, ..., 5.8, 5.9, 5]
and ([2, 7])
- Choose better names for variables – Why have you used uppercase
X
and then lowercase y
? What does i
, k
, and m
signify? General recommendation is to use variable names meaning something, longer than one character long. For loop counters there is an exception for i
, j
, k
, in that sequence.
- Strange combination of
i
and k
– When I read code having i
and k
, by convention I'm assuming there to be an j
somewhere. This is missing. In addition the i
is not a loop counter, but some predicate function for use with numpy's boolean arrays. Try finding a better name for i
, possibly something like marker_range_predicate
.
And then some considerations regarding your coding algorithm:
First of all I don't quite understand why you want to hide the y
-value and replace it with a flat value of 1
, and then use markers to denote the few distinct y-values. To me, intuitively, it would make more sense to add markers for given y-ranges, and interconnect markers of a given style with lines. This would show corresponding x-ranges and y-ranges of values
Limit the range of the plot – Your example plot has loads of empty space, which makes the entire plot look almost empty. If you use min
and max
, you can limit the plot better. If you want to avoid having the min and max values on the axes, you could cheat a little and subtract/add 0.5
to those values. (An even better version would be to calculate the range, and add/subtract a percentage of that range to be used as limits)
Separate x-ranges with different y-values for each marker – In a comment you state that you want to see if the values are linearly separable. To me that read as you might have overlapping x-ranges for different x-values, and you want to visualize this.
In your current code, if you switch the fourth element to y=2
, the markers would overlap, so I suggest changing the 1
when you set flat
to be the current marker index, i.e. k
. This way you would easily see the line of a current marker, but can also see if they are overlapping.
Change size of markers – If adding a parameter, s
, to your call to scatter
, you can change the marker size, and make them a little more prominent. I found 200
to a somewhat good size.
Adding more markers? – I don't know if it's an alternative for you to use even more markers, but I tried adding some more and extended your data array with two extra x-values with a y-value of 2.
Refactored code
import numpy as np
import matplotlib.pyplot as plt
%%matplotlib inline
fig = plt.figure()
axes = fig.add_axes((1, 1, 1, 1))
x = np.array([3, 3.2, 3.5, 3.7, 3.8, 3.9, 5, 5.5, 5.8, 5.9, 5, 5.8])
y = np.array([1, 1, 1, 3, 2, 1, 2, 2, 2, 1, 2, 3])
markers = ['^', 'o', 's', 'v', 'p']
for idx, marker in enumerate(markers):
i = (y == idx + 1)
flat = [idx + 1 for val in y[i]]
axes.scatter(x[i], flat, marker=marker, s=200)
axes.set_xlim([min(x) - 0.5, max(x) + 0.5])
axes.set_ylim([min(y) - 0.5, max(y) + 0.5])
This resulted in the following figure:
As you can see there is a lot more empty space, bigger markers, and even easier to see that in my slightly changed base data the x-ranges are not totally separable.
import numpy as np
andimport matplotlib.pyplot as plt
. \$\endgroup\$