How to use string as data for plotting in Matlab? - string

I want to use a words like, let's say, 'A', 'B' and 'C' on X-axis to show their corresponding properties on Y-axis. How can I write these strings on X-axis instead of numerical data?

Use 'XTick' and 'XTickLabel' properties of the axes handle.
Here's a simple example:
x = 1:5;
y = rand(size(x));
plot(x, y, 'b')
set(gca, 'XTick',1:5, 'XTickLabel',{'A' 'B' 'C' 'D' 'E'})

Set yourself up a cell with your letters (mine's called labels), then use the XTick property to set the same amount of ticks on the x axis as your label number. Finally, the XTickLabel property will write your labels to the x axis.
x = yourXdata;
y = yourYdata;
labels = {'A' 'B' 'C'};
plot(x, y);
set(gca, 'XTick', 1:3, 'XTickLabel', labels);

How to use CHARACTER Values instead of Numerical values in X axis.
to label x as T1 T2 T3 T4 just use this :
set(gca,'XTick',1:4,'XTickLabel',{'T1', 'T2', 'T3', 'T4'},'FontSize',15)
this command can be used after the plot command followed by the xlabel and ylabel , legand commands.
you can also adjust the font size.
Practical Example:
%% 50% Day
T1wSI=[54.17 115];
T2wSI=[53.5 112];
T3wSI=[52.2 110];
T4wSI=[51.2 108];
T1oSI=[50.25 94];
T2oSI=[49.18 92];
T3oSI=[48.2 90];
T4oSI=[46.1 84];
table1=[T1wSI;T2wSI;T3wSI;T4wSI;T1oSI;T2oSI;T3oSI;T4oSI ];
season2012=table1(:,1);
season2013=table1(:,2);
Tr1=[1 2 3 4];
Treatment1 =['T1wSI' 'T2wSI' 'T3wSI' 'T4wSI' 'T1oSI' 'T2oSI' 'T3oSI' 'T4oSI'];
%Tre1=['T1' 'T2' 'T3' 'T4'];
%set(gca,'FontSize',14)
figure(1)
set(gca,'XTick',1:4,'XTickLabel',{'T1', 'T2', 'T3', 'T4'},'FontSize',14)
plot(Tr1,table1(1:4,1),'--bs','LineWidth',3);% 2012
hold on;
plot(Tr1,table1(1:4,2),'-go','LineWidth',3);% 2013
plot(Tr1,table1(5:8,1),'--r*','LineWidth',3); % 2012
plot(Tr1,table1(5:8,2),'-m^','LineWidth',3);% 2013
set(gca,'XTick',1:4,'XTickLabel',{'T1', 'T2', 'T3', 'T4'},'FontSize',15)
xlim=[1 5];
xlabel('Treatments')
ylabel('Days to 50 % Flowering')
legend('With -Season 2012','Without -Season 2013','With -Season 2012','Without - Season 2013','Location','NorthEast');

You can also do this using the GUI.
1) Click on the figure axes to to open the Axes Property Editor.
2) Click on the "More properties" button on the right side of the window. This will open the inspector window of the axes.
3) Click on the small button next to "XTickLabel" property to open the dialogue box as shown below.
4) Enter the labels you want and click on "OK".

Related

Is it possible to extract the default tick locations from the primary axis and pass it to a secondary access with matplotlib?

When making a plot with with
fig, ax = plt.subplots()
x=[1,2,3,4,5,6,7,8,9,10]
y=[1,2,3,4,5,6,7,8,9,10]
ax.plot(x,y)
plt.show()
matplotlib will determine the tick spacing/location and value of the tick. Is there are way to extract this automatic spacing/location AND the value? I want to do this so i can pass it to
set_xticks()
for my secondary axis (using twiny()) then use set_ticklabels() with a custom label. I realise I could use secondary axes giving both a forward and inverse function however providing an inverse function is not feasible for the goal of my code.
So in the image below, the ticks are only showing at 2,4,6,8,10 rather than all the values of x and I want to somehow extract these values and position so I can pass to set_xticks() and then change the tick labels (on a second x axis created with twiny).
UPDATE
When using the fix suggested it works well for the x axis. However, it does not work well for the y-axis. For the y-axis it seems to take the dataset values for the y ticks only. My code is:
ax4 = ax.twinx()
ax4.yaxis.set_ticks_position('left')
ax4.yaxis.set_label_position('left')
ax4.spines["left"].set_position(("axes", -0.10))
ax4.set_ylabel(self.y_2ndary_label, fontweight = 'bold')
Y = ax.get_yticks()
ax4.yaxis.set_ticks(Y)
ax4.yaxis.set_ticklabels( Y*Y )
ax4.set_ylim(ax.get_ylim())
fig.set_size_inches(8, 8)
plt.show()
but this gives me the following plot. The plot after is the original Y axis. This is not the case when I do this on the x-axis. Any ideas?
# From "get_xticks" Doc: The locations are not clipped to the current axis limits
# and hence may contain locations that are not visible in the output.
current_x_ticks = ax.get_xticks()
current_x_limits = ax.get_xlim()
ax.set_yticks(current_x_ticks) # Use this before "set_ylim"
ax.set_ylim(current_x_limits)
plt.show()

Plot multi label (values) with multi bar chart

I've this issue I hope you can help.
I've this data :
to_stack = pd.DataFrame([['CHILDREN', 0.42806248287201976, 0.0],
['AMT_TOTAL', 165006, 179357],
['SAL', 582065, 703917.0],
['ANNUITY', 26851, 28416]], columns=('Variable','Id','Mean'))
When I run the code below
to_stack.plot.barh(x='Variable', figsize=(12,8), width = .9)
## First Loop for first Variable "ID"
for index,value in enumerate(to_stack['Id']):
plt.text(value, index, str(value), va='top', )
## Second Loop for Second Variable
for i,val in enumerate(to_stack['Mean']):
plt.text(val, i, str(val), va='bottom' )
I get this result
The Values in each bar ar not well centralized
I've tried several options in Matplotlib.plt.text (ha (center, left, right) , va (top, bottom, baseline) without good results, sometimes it's even worse, values are one on each other.
How can we get the values aligned with the bars ?
Any ideas are really welcome
It's better to extract information from the bars and annotate. That way, you have more control of how the text appears in relative to the bars:
fig, ax = plt.subplots(figsize=(12,8),)
to_stack.plot.barh(x='Variable', width = .9, ax=ax)
for patch in ax.patches:
w, h = patch.get_width(), patch.get_height()
y = patch.get_y()
ax.text(w + -0.1,h/2+y, f'{w:.3f}', va='center')
Output:

How to label line chart with column from pandas dataframe (from 3rd column values)?

I have a data set I filtered to the following (sample data):
Name Time l
1 1.129 1G-d
1 0.113 1G-a
1 3.374 1B-b
1 3.367 1B-c
1 3.374 1B-d
2 3.355 1B-e
2 3.361 1B-a
3 1.129 1G-a
I got this data after filtering the data frame and converting it to CSV file:
# Assigns the new data frame to "df" with the data from only three columns
header = ['Names','Time','l']
df = pd.DataFrame(df_2, columns = header)
# Sorts the data frame by column "Names" as integers
df.Names = df.Names.astype(int)
df = df.sort_values(by=['Names'])
# Changes the data to match format after converting it to int
df.Time=df.Time.astype(int)
df.Time = df.Time/1000
csv_file = df.to_csv(index=False, columns=header, sep=" " )
Now, I am trying to graph lines for each label column data/items with markers.
I want the column l as my line names (labels) - each as a new line, Time as my Y-axis values and Names as my X-axis values.
So, in this case, I would have 7 different lines in the graph with these labels: 1G-d, 1G-a, 1B-b, 1B-c, 1B-d, 1B-e, 1B-a.
I have done the following so far which is the additional settings, but I am not sure how to graph the lines.
plt.xlim(0, 60)
plt.ylim(0, 18)
plt.legend(loc='best')
plt.show()
I used sns.lineplot which comes with hue and I do not want to have name for the label box. Also, in that case, I cannot have the markers without adding new column for style.
I also tried ply.plot but in that case, I am not sure how to have more lines. I can only give x and y values which create only one line.
If there's any other source, please let me know below.
Thanks
The final graph I want to have is like the following but with markers:
You can apply a few tweaks to seaborn's lineplot. Using some created data since your sample isn't really long enough to demonstrate:
# Create data
np.random.seed(2019)
categories = ['1G-d', '1G-a', '1B-b', '1B-c', '1B-d', '1B-e', '1B-a']
df = pd.DataFrame({'Name':np.repeat(range(1,11), 10),
'Time':np.random.randn(100).cumsum(),
'l':np.random.choice(categories, 100)
})
# Plot
sns.lineplot(data=df, x='Name', y='Time', hue='l', style='l', dashes=False,
markers=True, ci=None, err_style=None)
# Temporarily removing limits based on sample data
#plt.xlim(0, 60)
#plt.ylim(0, 18)
# Remove seaborn legend title & set new title (if desired)
ax = plt.gca()
handles, labels = ax.get_legend_handles_labels()
ax.legend(handles=handles[1:], labels=labels[1:], title='New Title', loc='best')
plt.show()
To apply markers, you have to specify a style variable. This can be the same as hue.
You likely want to remove dashes, ci, and err_style
To remove the seaborn legend title, you can get the handles and labels, then re-add the legend without the first handle and label. You can also specify the location here and set a new title if desired (or just remove title=... for no title).
Edits per comments:
Filtering your data to only a subset of level categories can be done fairly easily via:
categories = ['1G-d', '1G-a', '1B-b', '1B-c', '1B-d', '1B-e', '1B-a']
df = df.loc[df['l'].isin(categories)]
markers=True will fail if there are too many levels. If you are only interested in marking points for aesthetic purposes, you can simply multiply a single marker by the number of categories you are interested in (which you have already created to filter your data to categories of interest): markers='o'*len(categories).
Alternatively, you can specify a custom dictionary to pass to the markers argument:
points = ['o', '*', 'v', '^']
mult = len(categories) // len(points) + (len(categories) % len(points) > 0)
markers = {key:value for (key, value)
in zip(categories, points * mult)}
This will return a dictionary of category-point combinations, cycling over the marker points specified until each item in categories has a point style.

Plot the distance between every two points in 2 D

If I have a table with three columns where the first column represents the name of each point, the second column represent numerical data (mean) and the last column represent (second column + fixed number). The following an example how is the data looks like:
I want to plot this table so I have the following figure
If it is possible how I can plot it using either Microsoft Excel or python or R (Bokeh).
Alright, I only know how to do it in ggplot2, I will answer regarding R here.
These method only works if the data-frame is in the format you provided above.
I rename your column to Name.of.Method, Mean, Mean.2.2
Preparation
Loading csv data into R
df <- read.csv('yourdata.csv', sep = ',')
Change column name (Do this if you don't want to change the code below or else you will need to go through each parameter to match your column names.
names(df) <- c("Name.of.Method", "Mean", "Mean.2.2")
Method 1 - Using geom_segment()
ggplot() +
geom_segment(data=df,aes(x = Mean,
y = Name.of.Method,
xend = Mean.2.2,
yend = Name.of.Method))
So as you can see, geom_segment allows us to specify the end position of the line (Hence, xend and yend)
However, it does not look similar to the image you have above.
The line shape seems to represent error bar. Therefore, ggplot provides us with an error bar function.
Method 2 - Using geom_errorbarh()
ggplot(df, aes(y = Name.of.Method, x = Mean)) +
geom_errorbarh(aes(xmin = Mean, xmax = Mean.2.2), linetype = 1, height = .2)
Usually we don't use this method just to draw a line. However, its functionality fits your requirement. You can see that we use xmin and ymin to specify the head and the tail of the line.
The height input is to adjust the height of the bar at the end of the line in both ends.
I would use hbar for this:
from bokeh.io import show, output_file
from bokeh.plotting import figure
output_file("intervals.html")
names = ["SMB", "DB", "SB", "TB"]
p = figure(y_range=names, plot_height=350)
p.hbar(y=names, left=[4,3,2,1], right=[6.2, 5.2, 4.2, 3.2], height=0.3)
show(p)
However Whisker would also be an option if you really want whiskers instead of interval bars.

How to insert text outside a plot

I have the following plot (with 3 rows and 4 columns):
f, ((ax1, ax2, ax3, ax4), (ax5, ax6, ax7, ax8), (ax9, ax10, ax11, ax12)) = plt.subplots(3, 4, sharex = 'col', sharey = 'row')
ax1.set_title('column1')
ax1.plot([x], [y])
ax5.plot([x1],[y1])
ax9.plot([x2],[y2])
ax2.set_title('column2')
ax2.plot([x3],[x4])
ax6.plot([x5],[x6])
.....
How is it possible to insert text outside the plot window? For each row I would like to write a sentence on the right end side of the plot.
You could use the ax.set_title() function.
Alternatively, you might want to place your text using the ax.text() function. Note that you can use values in the position argument that go beyond your axes ranges. Additionally, you can set the reference coordinate system using the transform parameter.

Resources