Representing row vector as a line plot in matplotlib - python

Let's say I have a row vector with the shape (1, 100). Call it row.
I want to display its values in a line plot. The x-axis displays the vector indices. The y-axis displays the values at the corresponding indices. How would you do it in matplotlib?
EDIT:
Here is what I have tried:
indices = [n for n in range(100)]
values = list(row[:, :100])
pyplot.plot(indices, values)

The array indices is not necessary.
The values array syntax is unclear... and an error in python, unless you are using numpy.
The following will plot an array of random values, with indices as x and the random numbers stored in values as y
import matplotlib.pyplot as plt
import random
# indices = [n for n in range(100)]
values = [random.random() for _ in range(100)]
plt.plot(values)
plt.show()

import matplotlib.pyplot as plt
indices = range(100) # already returns a list, no need to iterate again
values = # insert 1d vector here, what you seem to use is multi-dim
plt.plot(indices, values)
plt.show()

Related

Xarray add (as in sum) two rows along same dimension but at different coordinate value

I have used xarray to create two different DataArrays with the same dimensions and coordinates. However I want to add two different coordinates in one of these dimensions. I'm trying to add coordinate 'a' to coordinate 'b' in dimension 'x'. There is an easy workaround if these are the only dimensions of my matrix but more complicated if I have more dimensions and I want to keep the normal xarray behaviour for the other dimensions. Please see the example below that fails on the last line. I know how to manually fix this in numpy but the beauty of xarray is that I shouldn't have to.
Does xarray allow an easy solution for this kind of operation?
import xarray as xr
import numpy as np
# create simple DataArray M and N to show what I would like to do
M = xr.DataArray([1, 2], dims="x",coords={'x':['a','b']})
N = xr.DataArray([3, 4], dims="x",coords={'x':['a','b']})
print(M.sel(x='a')+N.sel(x='b')) # this will NOT give me the value
print(M.sel(x='a').values+N.sel(x='b').values) # this will give me the value
# create a more complex DataArray M and N to show what the challenge
m = np.arange(3*2*4)
m = m.reshape(3,2,4)
n = np.arange(4*2*3)
n = n.reshape(4,2,3)
M = xr.DataArray(m, dims=['z1',"x","z2"],coords={'x':['a','b']})
N = xr.DataArray(n, dims=["z2",'x','z1'],coords={'x':['a','b']})
print(M.sel(x='a')+N.sel(x='b')) # this will NOT give me the value
print(M.sel(x='a').values+N.sel(x='b').values) # this will result in an error

Plot 3rd axis of a 3D numpy array

I have a 3D numpy array that is a stack of 2D (m,n) images at certain timestamps, t. So my array is of shape (t, m, n). I want to plot the value of one of the pixels as a function of time.
e.g.:
import numpy as np
import matplotlib.pyplot as plt
data_cube = []
for i in xrange(10):
a = np.random(100,100)
data_cube.append(a)
So my (t, m, n) now has shape (10,100,100). Say I wanted a 1D plot the value of index [12][12] at each of the 10 steps I would do:
plt.plot(data_cube[:][12][12])
plt.show()
But I'm getting index out of range errors. I thought I might have my indices mixed up, but every plot I generate seems to be in the 'wrong' axis, i.e. across one of the 2D arrays, but instead I want it 'through' the vertical stack. Thanks in advance!
Here is the solution: Since you are already using numpy, convert you final list to an array and just use slicing. The problem in your case was two-fold:
First: Your final data_cube was not an array. For a list, you will have to iterate over the values
Second: Slicing was incorrect.
import numpy as np
import matplotlib.pyplot as plt
data_cube = []
for i in range(10):
a = np.random.rand(100,100)
data_cube.append(a)
data_cube = np.array(data_cube) # Added this step
plt.plot(data_cube[:,12,12]) # Modified the slicing
Output
A less verbose version that avoids iteration:
data_cube = np.random.rand(10, 100,100)
plt.plot(data_cube[:,12,12])

Accessing all elements of a row in python float array

I have searched long and hard and cannot find a way to do this.
x = random.normal(100,100)
This is a variable X of type float. I want to pass all the elements of the first column as X coordinates and the elements of the second column as Y coordinates to the matplotlib.pyplot function. How do I do it ?
Also how to determine the shape of a float array ? In this case it is clearly 100x100 but since float objects do not have a float.shape attribute.
Your np.random.normal(100,100) is a simple, single float...
Like so?
import matplotlib.pyplot as plt
import numpy as np
data = np.random.normal((100,100)*100) # 2 * 100 values = 200 values normalized around 100
x = data[0::2] take even as X
y = data[1::2] take uneven as Y
plt.scatter(x,y)
plt.plot(x,y)
plt.grid(True)
plt.show()
To elaborate slightly on #Patrick Artner's answer...
x = random.normal(100,100)
This generates one random variable from a normal distribution with mean = 100 and standard deviation = 100. To see the answer more clearly, you could specify keyword arguments as
x = np.random.normal(loc=100, scale=100)
Note: loc = mean and scale = standard deviation.
See numpy's documentation: https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.random.normal.html
To answer your question about how to determine the shape of a float array, you simply call the .shape function on a float array. For example:
x = np.random.normal(0, 1, (100, 2))
print("The shape of x is %s" % (x.shape,))

Plotting a heat map from three lists: X, Y, Intensity

I don't get how to create a heatmap (or contour plot) when I have x, y, intensity. I have a file which looks like this:
0,1,6
0,2,10
....
So far:
with open('eye_.txt', 'r') as f:
for line in f:
for word in line.split():
l = word.strip().split(',')
x.append(l[0])
y.append(l[1])
z.append(l[2])
Tried using pcolormesh but it wants a shape object and I'm unsure how to convert these lists into a NumPy array.
I tried:
i,j = np.meshgrid(x,y)
arr = np.array(z)
plt.pcolormesh(i,j,arr)
plt.show()
It tells me that:
IndexError: too many indices
Can someone stop me from bashing my head against a keyboard, please?
OK, there's a few steps to this.
First, a much simpler way to read your data file is with numpy.genfromtxt. You can set the delimiter to be a comma with the delimiter argument.
Next, we want to make a 2D mesh of x and y, so we need to just store the unique values from those to arrays to feed to numpy.meshgrid.
Finally, we can use the length of those two arrays to reshape our z array.
(NOTE: This method assumes you have a regular grid, with an x, y and z for every point on the grid).
For example:
import matplotlib.pyplot as plt
import numpy as np
data = np.genfromtxt('eye_.txt',delimiter=',')
x=data[:,0]
y=data[:,1]
z=data[:,2]
## Equivalently, we could do that all in one line with:
# x,y,z = np.genfromtxt('eye_.txt', delimiter=',', usecols=(0,1,2))
x=np.unique(x)
y=np.unique(y)
X,Y = np.meshgrid(x,y)
Z=z.reshape(len(y),len(x))
plt.pcolormesh(X,Y,Z)
plt.show()
In case you don't have a regular grid (i.e. a value of z for each meshgrid value of x and y), you can use a more general method based on pandas data frames:
import pandas as pd
import seaborn as sns
import matplotlib.pypot as plt
data = pd.DataFrame(data={'x':x, 'y':y, 'z':z})
data = data.pivot(index='x', columns='y', values='z')
sns.heatmap(data)
plt.show()
The pivot method will use unique values from index and columns to construct a table with missing measurments set to NaN. The table can then be plotted as a heatmap.
The index error arises from the fact that pcolormesh expects a 2D array while your arr is a 1D vector. Also if I understand correctly, your input file has the form
0,1,z
0,2,z
...
0,ymax,z
...
1,1,z
1,2,z
...
xmax,ymax,z
In that case meshgrid(x,y) will not work as it expects something like meshgrid(range(xmax),range(ymax)) i.e. vectors without repeated values.
In your case you need to find out how many distinct x and y values there are and then simply reshape your vectors into 2D arrays.
shape = np.unique(x).shape[0],np.unique(y).shape[0]
x_arr = x.reshape(shape)
y_arr = y.reshape(shape)
z_arr = z.reshape(shape)
plt.pcolormesh(x_arr,y_arr,z_arr)
To convert a list into a numpy array you can use np.asarray.
Here's an easy way to get a heatmap, you should be able to adapt this example to your problem.
import matplotlib.pyplot as plt
import numpy as np
a = [[1,2,3], [3,4,5], [5,6,7], [7, 8, 9]]
b = np.asarray(a)
plt.pcolor(b)
plt.show()
To read the data in like a list of lists you can do:
a = []
for line in file.readlines():
a.append( map( int, line.split(',') ) )
in short. In a longer version it's the equivalent of:
a = []
for line in file.readlines():
tmp = line.split(',')
inttmp = [int(x) for x in a]
a.append(inttmp)

Interpolate each row in matrix of x values

I want to interpolate between values in each row of a matrix (x-values) given a fixed vector of y-values. I am using python and essentially I need something like scipy.interpolate.interp1d but with x values being a matrix input. I implemented this by looping, but I want to make the operation as fast as possible.
Edit
Below is an example of a code of what I am doing right now, note that my matrix has more rows on order of millions:
import numpy as np
x = np.linspace(0,1,100).reshape(10,10)
results = np.zeros(10)
for i in range(10):
results[i] = np.interp(0.1,x[i],range(10))
As #Joe Kington suggested you can use map_coordinates:
import scipy.ndimage as nd
# your data - make sure is float/double
X = np.arange(100).reshape(10,10).astype(float)
# the points where you want to interpolate each row
y = np.random.rand(10) * (X.shape[1]-1)
# the rows at which you want the data interpolated -- all rows
r = np.arange(X.shape[0])
result = nd.map_coordinates(X, [r, y], order=1, mode='nearest')
The above, for the following y:
array([ 8.00091648, 0.46124587, 7.03994936, 1.26307275, 1.51068952,
5.2981205 , 7.43509764, 7.15198457, 5.43442468, 0.79034372])
Note, each value indicates the position in which the value is going to be interpolated for each row.
Gives the following result:
array([ 8.00091648, 10.46124587, 27.03994936, 31.26307275,
41.51068952, 55.2981205 , 67.43509764, 77.15198457,
85.43442468, 90.79034372])
which makes sense considering the nature of the aranged data, and the columns (y) at which it is interpolated.

Categories