How to Plot a List of Vectors with Different Lengths

How to plot a list of vectors with different lengths?

Using a made up example:

# example data:
dat <- list(a=1:5,b=2:7,c=3:10)
# get plotting:
plot(unlist(dat),type="n",xlim=c(1,max(sapply(dat,length))))
mapply(lines,dat,col=seq_along(dat),lty=2)
legend("topleft",names(dat),lty=2,col=seq_along(dat))

Sample Image

How to plot arrays of different lengths

If I am understanding correctly, this can be done by using two different axes which share the same y-axis, as outlined in this matplotlib example.

In your case you can accomplish this by making the following modifications:

from scipy import interpolate
import matplotlib.pyplot as plt
import numpy as np
num_points = 100

# Generate an array of data, interpolate, re-sample and graph
x1 = np.arange(0, num_points)
y1 = np.cos(x1)
f1 = interpolate.interp1d(x1, y1, kind='cubic')
xnew1 = np.arange(0, num_points - 1, 0.2)
ynew1 = f1(xnew1)

fig, ax1 = plt.subplots() # Create the first axis

ax1.plot(x1, y1, color='g', label='input 1')
ax1.plot(x1, y1, 'o', color='g')
ax1.plot(xnew1, ynew1, color='m', label='interp 1')
ax1.plot(xnew1, ynew1, '+', color='m')

ax2 = ax1.twiny() # Create a twin which shares the y-axis

# Generate an array different size of data, interpolate, re-sample and graph
x2 = np.arange(0, num_points/2)
y2 = np.sin(x2)
f2 = interpolate.interp1d(x2, y2, kind='cubic')
xnew2 = np.arange(0, (num_points/2) - 1, 0.2)
ynew2 = f2(xnew2)

ax2.plot(x2, y2, color='k', label='input 2')
ax2.plot(x2, y2, 'o', color='k')
ax2.plot(xnew2, ynew2, color='r', label='interp 2')
ax2.plot(xnew2, ynew2, '+', color='r')
plt.figlegend(loc='upper left', bbox_to_anchor=(0.065, 0.3, 0.5, 0.5))
plt.show()

This will give you something that looks like

Output from modified code

Edit

In order to properly display the legend you can construct one legend for all the subplots, as outlined in this demo. Note that using this method will require some manhandling of the bounding box for the legend, and there are much cleaner ways to do this than specifying a 4-tuple of floats as I have in the line

plt.figlegend(loc='upper left', bbox_to_anchor=(0.065, 0.3, 0.5, 0.5))

ggplot2 plotting two vectors of different lengths from when the smaller one begins

Thanks for the update! Let me call your data d

d <- structure(list(Date = structure(c(5L, 6L, 7L, 8L, 1L, 2L, 3L, 
4L), .Label = c("1/3/1928", "1/4/1928", "1/5/1928", "1/6/1928",
"12/28/1927", "12/29/1927", "12/30/1927", "12/31/1927"), class = "factor"),
DJIA = c(198.6, 199.96, 200.7, 202.4, 203.35, 202.24, 199.61,
201.45), SPX = c(NA, NA, NA, NA, 17.76, 17.72, 17.55, 17.66
)), .Names = c("Date", "DJIA", "SPX"), class = "data.frame", row.names = c(NA,
-8L))

The first problem with this data is that Date is a factor, to plot correctly we need to first change it to a Date,

d$Date <- as.Date(d$Date, "%m/%d/%Y")

The easiest way to achieve your desired output is to remove the NA as follows

 ggplot(d[complete.cases(d[,c("Date", "SPX")]), ], aes(x = Date, y = SPX)) +
geom_line()

However, I suspect you'll be generating a lot of these figures. It might be a better idea to create you own plot function.

myplot <- function(data, myX, myY){
data <- data[complete.cases(data[,c(myX, myY)]), ]
ggplot(data, aes_string(x = myX, y = myY))+
geom_line()
}

Notice the aes_string, this simplifies the passing of the variable names. It is possible to use aes, but its a bit more complicated.

With this function you can plot each columns with the code

myCOL <- c("DJIA", "SPX") #names of columns, note they are in quotes.  This is because we're using aes_string

allPLOT <- lapply(myCOL, function(x) myplot(d, "Date", x))

names(allPLOT) <- myCOL #naming the elements of the list

All the plots are now stored in a list for example you can obtain the plot for SPX by calling

allPLOT$SPX

How can you generate multiple vectors of different length in R?

You could use the following function:

make_vectors <- function(n) lapply(seq(n), function(i) seq(sample(i^2, 1)))

Which allows:

vector <- make_vectors(5)

vector
#> [[1]]
#> [1] 1
#>
#> [[2]]
#> [1] 1 2 3 4
#>
#> [[3]]
#> [1] 1 2 3 4
#>
#> [[4]]
#> [1] 1 2 3 4 5 6
#>
#> [[5]]
#> [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

And you can access each one like this:

vector[[5]]
#> [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

This keeps your global environment tidy and allows you to iterate through your vectors more easily than writing them all as independent entities.

Plotting a graph using vectors of different length in R

plot(cbind(v[1], result[1,])) will recycle v[1] as necessary.

Plot arrays of different lengths

If I'm not mistaken, using plot like you did plots 3 graphs with, for each, ks as x and bgd_costs, sgd_costs and mbgd_costs as 3 different y.
You obviously need x and y to have the same length and like you and the error says, it's not the case.

To make it work, you could add a "hold" and a split the display of the plots:

import matplotlib.pyplot as plt

plt.hold(True)
plt.plot(bgds, bgd_costs, 'b--')
plt.plot(sgds, sgd_costs, 'g-.')
plt.plot(mgbds, mbgd_costs, 'r')
plt.title("Blue-- = BGD, Green-. = SGD, Red=MBGD")
plt.ylabel('Cost')
plt.xlabel('Number of updates (k)')
plt.show()

Note the different x axes.

If you don't add a hold, every plot will erase the figure first.

Plotting multiple vectors of different lengths on the same figure

  1. In MATLAB traces sent to same plot must have same length.

  2. I have allocated just one variable containing all traces, for the respective tridiagonals and resulting traces out of your jacobi function.

  3. I have shortened from 2500 to 250, and the reason is that with 2500, compared to 50, the tridiag traces, and the short jacobi are so flat compared to the last trace than one has to recur to dB scale to find them on same graph window as you asked.

  4. 1st generate all data, and then plot all data.

So here you have the script plotting all traces in same graph :

clear all;close all;clc

n=[50 250];

us_ol=zeros(numel(n),max(n));

% generate data
for k=[1:1:numel(n)]
di=2*ones(n(k),1);
up=-ones(n(k),1);
lo=-ones(n(k),1);
b=ones(n(k),1)/(n(k)*n(k));
[subl,du,supu]=tridiag_factor(lo,di,up);
us_ol0 = tridiag_solve(subl,du,supu,b);
us_ol(k,[1:numel(us_ol0)])=us_ol0;
end

n_us_ol=[1:1:size(us_ol,2)];

str1=['tridiag ' num2str(n(1))];
str2=['tridiag ' num2str(n(2))];
legend(str1,str2);
grid on

% the jacobi traces

nstp=1e3;
tol=1e-6;

A1=zeros(max(n),max(n),numel(n));

for k=1:1:numel(n)
A0=full(gallery('tridiag', n(k), -1, 2, -1));
A1([1:1:size(A0,1)],[1:1:size(A0,2)],k)=A0;
end

b_A1=ones(max(n),max(n),numel(n));

for k=1:1:numel(n)

for i=1:n(k)
b_A1(i,1,k)=0.0004;
end

end

n_A1=[1:1:size(A1,1)];

jkb=zeros(numel(n),max(n));

for k=1:1:numel(n)
A0=A1([1:n(k)],[1:n(k)],k);
b_A0=b_A1([1:n(k)],[1:n(k)],k);
n0=[1:1:n(k)];
jkb0=jacobi(A0,b_A0,n0',tol,nstp)
jkb(k,[1:numel(jkb0)])=jkb0';
end

% plot data
figure(1)
ax1=gca
plot(ax1,n_us_ol,us_ol(1,:),n_us_ol,us_ol(2,:));
hold(ax1,'on')
plot(ax1,n_A1,jkb(1,:),n_A1,jkb(2,:))

grid on
legend('3/1','3/2','jkb1','jkb2')
title('3diags and jakobians graph')

Sample Image

As mentioned above, one has to zoom to find some of the traces

Sample Image

One way to combine really small traces with large traces is to use Y log scale

figure(2)
ax2=gca
plot(ax2,n_us_ol,10*log10(us_ol(1,:)),n_us_ol,10*log10(us_ol(2,:)));
hold(ax2,'on')
plot(ax2,n_A1,10*log10(jkb(1,:)),n_A1,10*log10(jkb(2,:)))

grid on
legend('3/1[dB]','3/2[dB]','jkb1[dB]','jkb2[dB]')
title('3diags and jakobians graph in dB')

Sample Image

Plotting two different arrays of different lengths

As rth suggested, define

x1 = np.linspace(0, 1, 1000)
x2 = np.linspace(0, 1, 100)

and then plot raw versus x1, and smooth versus x2:

plt.plot(x1, raw)
plt.plot(x2, smooth)

np.linspace(0, 1, N) returns an array of length N with equally spaced values from 0 to 1 (inclusive).


import numpy as np
import matplotlib.pyplot as plt
np.random.seed(2015)

raw = (np.random.random(1000) - 0.5).cumsum()
smooth = raw.reshape(-1,10).mean(axis=1)

x1 = np.linspace(0, 1, 1000)
x2 = np.linspace(0, 1, 100)
plt.plot(x1, raw)
plt.plot(x2, smooth)
plt.show()

yields
Sample Image



Related Topics



Leave a reply



Submit