My dataframe is:
X=[0,1,2
1,0,3
2,3,0]
X shape is 3*3.
For every value, I want to expand n times in every row and column, that is, transform my dataframe to the shape of (3*n)*(3*n),
if n=2, my ideal result is:
X=[0,0,1,1,2,2
0,0,1,1,2,2
1,1,0,0,3,3
1,1,0,0,3,3
2,2,3,3,0,0
2,2,3,3,0,0]
How to do that? thanks!
One way using pandas.Index.repeat:
ind = df.index.repeat(2)
new_df = df.iloc[ind, ind]
print(new_df)
Output:
0 0 1 1 2 2
0 0 0 1 1 2 2
0 0 0 1 1 2 2
1 1 1 0 0 3 3
1 1 1 0 0 3 3
2 2 2 3 3 0 0
2 2 2 3 3 0 0
You could use numpy.repeat, as follows:
import numpy as np
X = np.array([[0, 1, 2],
[1, 0, 3],
[2, 3, 0]] )
res = X.repeat(2, axis=1).repeat(2, axis=0)
print(res)
Output
[[0 0 1 1 2 2]
[0 0 1 1 2 2]
[1 1 0 0 3 3]
[1 1 0 0 3 3]
[2 2 3 3 0 0]
[2 2 3 3 0 0]]
A base python solution (without imports) would be a nested list comprehension:
>>> [[y for y in x for _ in range(3)] for x in X for _ in range(3)]
[[0, 0, 0, 1, 1, 1, 2, 2, 2],
[0, 0, 0, 1, 1, 1, 2, 2, 2],
[0, 0, 0, 1, 1, 1, 2, 2, 2],
[1, 1, 1, 0, 0, 0, 3, 3, 3],
[1, 1, 1, 0, 0, 0, 3, 3, 3],
[1, 1, 1, 0, 0, 0, 3, 3, 3],
[2, 2, 2, 3, 3, 3, 0, 0, 0],
[2, 2, 2, 3, 3, 3, 0, 0, 0],
[2, 2, 2, 3, 3, 3, 0, 0, 0]]
>>>
Related
Just wondering if there's a function that can produce an nxn array where the centre has the maximum value, and the edges have a value of 0 like so:
0 0 0 0 0 0 0
0 1 1 1 1 1 0
0 1 2 2 2 1 0
0 1 2 3 2 1 0
0 1 2 2 2 1 0
0 1 1 1 1 1 0
0 0 0 0 0 0 0
Would be nice if there was something similar to np.arange where I can just insert n and get an array like the one above, but I'm not too hopeful.
I don't think there is a built-in for this. But you can build one:
def get_center(size):
a = np.minimum(np.arange(size), size - 1 - np.arange(size))
return np.minimum(a, a[:,None])
get_center(7)
Out:
array([[0, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 1, 1, 1, 0],
[0, 1, 2, 2, 2, 1, 0],
[0, 1, 2, 3, 2, 1, 0],
[0, 1, 2, 2, 2, 1, 0],
[0, 1, 1, 1, 1, 1, 0],
[0, 0, 0, 0, 0, 0, 0]])
This question already has answers here:
Quick way to upsample numpy array by nearest neighbor tiling [duplicate]
(3 answers)
Closed 2 years ago.
Suppose I have a numpy array that looks like this
[[0 1]
[2 3]]
How do I pad the values from the centers to produce a one like
[[0 0 0 1 1 1]
[0 0 0 1 1 1]
[0 0 0 1 1 1]
[2 2 2 3 3 3]
[2 2 2 3 3 3]
[2 2 2 3 3 3]
np.pad is your friend here. The mode=edge argument makes sure that the padded values are taken from the closest element in the original array:
np.pad([[0, 1], [2, 3]], 2, mode='edge')
>>> array([[0, 0, 0, 1, 1, 1],
[0, 0, 0, 1, 1, 1],
[0, 0, 0, 1, 1, 1],
[2, 2, 2, 3, 3, 3],
[2, 2, 2, 3, 3, 3],
[2, 2, 2, 3, 3, 3]])
I have a requirement where I want to convert a 2D matrix to 3D by separating 3 unique values across 3 dimensions.
For Example:
convert
A = [1 2 3 3
1 1 2 1
3 2 2 3
1 3 3 2]
to
A = [[1 0 0 0
1 1 0 1
0 0 0 0
1 0 0 0]
[0 1 0 0
0 0 1 0
0 1 1 0
0 0 0 1]
[0 0 1 1
0 0 0 0
1 0 0 1
0 1 1 0]]
Pardon me if the syntax of matrix representation is not correct.
Use broadcasting with outer-equality for a vectorized solution -
# Input array
In [8]: A
Out[8]:
array([[1, 2, 3, 3],
[1, 1, 2, 1],
[3, 2, 2, 3],
[1, 3, 3, 2]])
In [11]: np.equal.outer(np.unique(A),A).view('i1')
Out[11]:
array([[[1, 0, 0, 0],
[1, 1, 0, 1],
[0, 0, 0, 0],
[1, 0, 0, 0]],
[[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 1, 1, 0],
[0, 0, 0, 1]],
[[0, 0, 1, 1],
[0, 0, 0, 0],
[1, 0, 0, 1],
[0, 1, 1, 0]]], dtype=int8)
To use the explicit dimension-extension + comparison, it would be :
(A == np.unique(A)[:,None,None]).view('i1')
You can use np.unique and take advantage of boolean arrays and cast them to int using numpy.ndarray.astype.
import numpy as np
a=np.array([[1, 2, 3, 3], [1, 1, 2, 1], [3, 2, 2, 3], [1, 3, 3, 2]])
[a==i.astype(int) for i in np.unique(a)]
Output:
[array([[1, 0, 0, 0],
[1, 1, 0, 1],
[0, 0, 0, 0],
[1, 0, 0, 0]]),
array([[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 1, 1, 0],
[0, 0, 0, 1]]),
array([[0, 0, 1, 1],
[0, 0, 0, 0],
[1, 0, 0, 1],
[0, 1, 1, 0]])]
EDIT: Ch3steR's answer is better
A = np.array([[1,2,3,3], [1,1,2,1], [3,2,2,3], [1,3,3,2]])
unique_values = np.unique(A)
B = np.array([np.zeros_like(A) for i in range(len(unique_values))])
for idx, value in enumerate(unique_values):
B[idx][A == value] = 1
In numpy is it possible to make a difference between this 2 arrays:
[[0 0 0 0 1 1 1 1 2 2 2 2]
[0 1 2 3 0 1 2 3 0 1 2 3]]
[[0 0 0 0 1 1 1 2 2 2]
[0 1 2 3 0 2 3 0 1 2]]
to have this result
[[1 2]
[1 3]]
?
This is one way. You can also use numpy.unique for a similar solution (easier in v1.13+, see Find unique rows in numpy.array), but if performance is not an issue you can use set.
import numpy as np
A = np.array([[0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2],
[0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3]])
B = np.array([[0, 0, 0, 0, 1, 1, 1, 2, 2, 2],
[0, 1, 2, 3, 0, 2, 3, 0, 1, 2]])
res = np.array(list(set(map(tuple, A.T)) - set(map(tuple, B.T)))).T
array([[2, 1],
[3, 1]])
We can think 2D array as 2 times of 1D array and using numpy.setdiff1d to compare them.
What about:
a=[[0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2], [0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3]]
b=[[0, 0, 0, 0, 1, 1, 1, 2, 2, 2], [0, 1, 2, 3, 0, 2, 3, 0, 1, 2]]
a = np.array(a).T
b = np.array(b).T
A = [tuple(t) for t in a]
B = [tuple(t) for t in b]
set(A)-set(B)
Out: {(1, 1), (2, 3)}
I have a 3D bar plot in matplotlib which consists of a total 165 bars and at the moment it is quite chaotic.
.
I would like to change the colour of the bars based on the discreet z-values: 0,1,2.
I know there is the option to change colour bar in 1D bar plots based on specific values by using masks as in Color matplotlib bar chart based on value.
And there is also a question on how to change bar colour based on values:
Defining colors of Matplotlib 3D bar plot
I am not sure If i perfectly comprehend the given answer but I cannot make it work in this case.
Code is:
data = [[0 0 0 2 0 0 1 2 0 0 0]
[0 0 2 2 0 0 0 0 2 0 0]
[1 0 2 2 1 2 0 0 2 0 2]
[1 0 2 2 0 2 0 2 2 2 2]
[2 2 2 2 2 2 2 2 2 2 2]
[2 2 0 2 2 2 2 2 2 2 2]
[0 2 2 0 2 2 2 2 2 2 2]
[1 2 0 0 2 1 2 2 0 0 2]
[0 0 2 1 0 0 2 0 0 0 0]
[2 1 2 2 0 0 0 2 0 0 2]
[2 2 2 0 2 0 0 0 2 2 2]
[2 2 0 0 2 2 2 2 2 0 0]
[2 2 1 2 0 0 0 2 2 2 0]
[2 0 0 2 0 0 2 2 2 2 2]
[2 0 0 2 0 2 2 2 2 2 2]]
ly = len(data[0])
lx = len(data[:,0])
xpos = np.arange(0,lx,1) # Set up a mesh of positions
ypos = np.arange(0,ly,1)
xpos, ypos = np.meshgrid(xpos+0.25, ypos+0.25)
xpos = xpos.flatten() # Convert positions to 1D array
ypos = ypos.flatten()
zpos = np.zeros(lx*ly)
dx = 0.5 * np.ones_like(zpos)
dy = dx.copy()
dz = data.flatten()
ys = np.array([float(yi) for yi in y[1:]])
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# all blue bars
#ax.bar3d(xpos,ypos,zpos, dx, dy, dz, color='b')
# try changing color bars
colors = ['r','g','b']
for i in range(0,3):
ax.bar3d(xpos[i], ypos[i], zpos[i], dx, dy, dz[i], alpha=0.1,
color=colors[i])
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
plt.show()
As seen from the documentation of bar3d, color can be an array, with one color per bar.
This makes it quite easy to colorize all bars in a single call to bar3d; we just need to convert the data array to an array of colors which can be done using a colormap,
colors = plt.cm.jet(data.flatten()/float(data.max()))
(Note, that a colormap takes values between 0 and 1, so we need to normalize the values into this range.)
Complete example:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
data = np.array([ [0, 0, 0, 2, 0, 0, 1, 2, 0, 0, 0],
[0, 0, 2, 2, 0, 0, 0, 0, 2, 0, 0],
[1, 0, 2, 2, 1, 2, 0, 0, 2, 0, 2],
[1, 0, 2, 2, 0, 2, 0, 2, 2, 2, 2],
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
[2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2],
[0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2],
[1, 2, 0, 0, 2, 1, 2, 2, 0, 0, 2],
[0, 0, 2, 1, 0, 0, 2, 0, 0, 0, 0],
[2, 1, 2, 2, 0, 0, 0, 2, 0, 0, 2],
[2, 2, 2, 0, 2, 0, 0, 0, 2, 2, 2],
[2, 2, 0, 0, 2, 2, 2, 2, 2, 0, 0],
[2, 2, 1, 2, 0, 0, 0, 2, 2, 2, 0],
[2, 0, 0, 2, 0, 0, 2, 2, 2, 2, 2],
[2, 0, 0, 2, 0, 2, 2, 2, 2, 2, 2]])
ypos, xpos = np.indices(data.shape)
xpos = xpos.flatten()
ypos = ypos.flatten()
zpos = np.zeros(xpos.shape)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
colors = plt.cm.jet(data.flatten()/float(data.max()))
ax.bar3d(xpos,ypos,zpos, .5,.5,data.flatten(), color=colors)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
plt.show()