I would like to convert the following python code into julia:
import numpy as np
x = np.random.random([4,5,6])
y = np.array([[x, x, x ],
[2*x,3*x,4*x]])
print(y.shape)
-> (2, 3, 4, 5, 6)
In julia, the analogous syntax seems to me is
x = rand(4,5,6)
y = [x x x; 2x 3x 4x]
println(size(y))
-> (8, 15, 6)
These results are different. Can you tell me how to do it?
Using random numbers and multipliers obscures the details which you seek. Let's do consecutive numbering and try to get Python and Julia to display alike:
python>>>>>> z = np.reshape(np.array(range(1,121)), [4, 5, 6])
>>> z
array([[[ 1, 2, 3, 4, 5, 6],
[ 7, 8, 9, 10, 11, 12],
[ 13, 14, 15, 16, 17, 18],
[ 19, 20, 21, 22, 23, 24],
[ 25, 26, 27, 28, 29, 30]],
[[ 31, 32, 33, 34, 35, 36],
[ 37, 38, 39, 40, 41, 42],
[ 49, 50, 51, 52, 53, 54],
[ 55, 56, 57, 58, 59, 60]],
[[ 61, 62, 63, 64, 65, 66],
[ 67, 68, 69, 70, 71, 72],
[ 73, 74, 75, 76, 77, 78],
[ 79, 80, 81, 82, 83, 84],
[ 85, 86, 87, 88, 89, 90]],
[[ 91, 92, 93, 94, 95, 96],
[ 97, 98, 99, 100, 101, 102],
[103, 104, 105, 106, 107, 108],
[109, 110, 111, 112, 113, 114],
[115, 116, 117, 118, 119, 120]]])
julia>z = reshape(1:120, 6, 5, 4)
6×5×4 reshape(::UnitRange{Int64}, 6, 5, 4) with eltype Int64:
[:, :, 1] =
1 7 13 19 25
2 8 14 20 26
3 9 15 21 27
4 10 16 22 28
5 11 17 23 29
6 12 18 24 30
[:, :, 2] =
31 37 43 49 55
32 38 44 50 56
33 39 45 51 57
34 40 46 52 58
35 41 47 53 59
36 42 48 54 60
[:, :, 3] =
61 67 73 79 85
62 68 74 80 86
63 69 75 81 87
64 70 76 82 88
65 71 77 83 89
66 72 78 84 90
[:, :, 4] =
91 97 103 109 115
92 98 104 110 116
93 99 105 111 117
94 100 106 112 118
95 101 107 113 119
96 102 108 114 120
So, if you want things to print similarly on the screen, you need to swap first and last dimension sizes (reverse the order of dimensions) on the arrays between Julia and Python. In addition, since Julia concatenates the arrays when you put them in the same brackets, but Python just nests its arrays in greater depth, you need to use np.reshape on Python or reshape on Julia to change the arrays to the shape you want. I suggest you check the resulting arrays on a consecutive set of integers to be sure they print alike before going back to your random floating point numbers. Remember that the indexing order is different when you access elements, too. Consider
>>> zzz = np.array([[z,z,z], [z,z,z]]) # python
> zzz = reshape([z z z; z z z], 6, 5, 4, 3, 2) # julia
Related
Lst's say there is a matrix A
A = [[ 34 61 29 74(17)32 72 92 93 57 ]
[(46)10 23 84 74 57 56 88 90 36 ]
[ 23(83)58 42 93 54 82 48 63 73 ]]
and a vector b of size 3
b = [4, 0, 1]
Does numpy has any function that would do the following job?
>>>A.choose_row_wise(b)
would output:
[17, 46, 83]
With numpy.take_along_axis:
b = np.array([4, 0, 1])
res = np.take_along_axis(A, b[:, None], axis=1).flatten()
print(res)
[17 46 83]
This can be done using indexing.
import numpy as np
A = np.array([[34, 61, 29, 74, 17, 32, 72, 92, 93, 57],[46, 10, 23, 84, 74, 57, 56, 88, 90, 36],[23, 83, 58, 42, 93, 54, 82, 48, 63, 73]])
b = np.array([4, 0, 1])
result = A[np.arange(len(b)), b]
[17 46 83]
Maybe you can use the following code:
import numpy as np
A = np.array([[34,61,29,74,(17),32,72,92,93,57],[(46),10,23,84,74,57,56,88,90,36],[23,(83),58,42,93,54,82,48,63,73]])
b = [4, 0, 1]
print([A[b.index(i), i] for i in b])
My code should compare the values on the bottom row and then add the highest out of each pair to the corresponding number above/adjacent to it. It works for the first row but doesn't iterate to get to the top.
Find the maximum total from top to bottom of the triangle below:
numbers = [
[75],
[95, 64],
[17, 47, 82],
[18, 35, 87, 10],
[20, 4, 82, 47, 65],
[19, 1, 23, 75, 3, 34],
[88, 2, 77, 73, 7, 63, 67],
[99, 65, 4, 28, 6, 16, 70, 92],
[41, 41, 26, 56, 83, 40, 80, 70, 33],
[41, 48, 72, 33, 47, 32, 37, 16, 94, 29],
[53, 71, 44, 65, 25, 43, 91, 52, 97, 51, 14],
[70, 11, 33, 28, 77, 73, 17, 78, 39, 68, 17, 57],
[91, 71, 52, 38, 17, 14, 91, 43, 58, 50, 27, 29, 48],
[63, 66, 4, 68, 89, 53, 67, 30, 73, 16, 69, 87, 40, 31],
[4, 62, 98, 27, 23, 9, 70, 98, 73, 93, 38, 53, 60, 4, 23]]
row = 14
col = 0
for j in range(14):
for i in range(len(numbers[row-1])):
if numbers[row][col] > numbers[row][col+1]:
numbers[row-1][col] += numbers[row][col]
col += 1
elif numbers[row][col] == numbers[row][col+1]:
numbers[row-1][col] += numbers[row][col]
col += 1
else:
numbers[row - 1][col] += numbers[row][col+1]
col += 1
row -= 1
col = 0
Here you go:
def get_max_sum(triangle, row_index):
if row_index == len(triangle):
return max(triangle[row_index - 1])
row = triangle[row_index]
previous_row = triangle[row_index - 1]
row[0] += previous_row[0]
for i in range(1, len(previous_row)):
row[i] += max(previous_row[i], previous_row[i - 1])
row[-1] += previous_row[-1]
triangle[row_index] = row
return get_max_sum(triangle, row_index + 1)
max_sum = get_max_sum(numbers, 1)
print(f'Max sum = {max_sum}')
Here is my solution based on the same logic used by you.
tri = """
75
95 64
17 47 82
18 35 87 10
20 04 82 47 65
19 01 23 75 03 34
88 02 77 73 07 63 67
99 65 04 28 06 16 70 92
41 41 26 56 83 40 80 70 33
41 48 72 33 47 32 37 16 94 29
53 71 44 65 25 43 91 52 97 51 14
70 11 33 28 77 73 17 78 39 68 17 57
91 71 52 38 17 14 91 43 58 50 27 29 48
63 66 04 68 89 53 67 30 73 16 69 87 40 31
04 62 98 27 23 09 70 98 73 93 38 53 60 04 23
"""
tri = tri.split("\n")[1:-1]
tri = [list(map(int, ele.split())) for ele in tri]
for row in range(len(tri)-2, -1, -1):
for ind, ele in enumerate(tri[row]):
if tri[row+1][ind] > tri[row+1][ind+1]:
tri[row][ind] += tri[row+1][ind]
else:
tri[row][ind] += tri[row+1][ind+1]
tri.pop()
print("Max sum:", tri[0][0])
I have an nxn numpy array, and I would like to divide it evenly into nxn tiles and randomly shuffle these, while retaining the pattern inside the tiles.
For example, if I have an array that's size (200,200), I want to be able to divide this into say 16 arrays of size (50,50), or even 64 arrays of size (25,25), and randomly shuffle these, while retaining the same shape of the original array (200,200) and retaining the order of numbers inside of the smaller arrays.
I have looked up specific numpy functions, and I found the numpy.random.shuffle(x) function, but this will randomly shuffle the individual elements of an array. I would only like to shuffle these smaller arrays within the larger array.
Is there any numpy function or quick way that will do this? I'm not sure where to begin.
EDIT: To further clarify exactly what I want:
Let's say I have an input 2D array of shape (10,10) of values:
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47 48 49
50 51 52 53 54 55 56 57 58 59
60 61 62 63 64 65 66 67 68 69
70 71 72 73 74 75 76 77 78 79
80 81 82 83 84 85 86 87 88 89
90 91 92 93 94 95 96 97 98 99
I choose a tile size such that it fits evenly into this array, so since this array has shape (10,10), I can either choose to split this into 4 (5,5) tiles, or 25 (2,2) tiles. So if I choose 4 (5,5) tiles, I want to randomly shuffle these tiles that results in an output array that could look like this:
50 51 52 53 54 0 1 2 3 4
60 61 62 63 64 10 11 12 13 14
70 71 72 73 74 20 21 22 23 24
80 81 82 83 84 30 31 32 33 34
90 91 92 93 94 40 41 42 43 44
55 56 57 58 59 5 6 7 8 9
65 66 67 68 69 15 16 17 18 19
75 76 77 78 79 25 26 27 28 29
85 86 87 88 89 35 36 37 38 39
95 96 97 98 99 45 46 47 48 49
Every array (both the input array, the output array, and the separate tiles) would be squares, so that when randomly shuffled the size and dimension of the main array stays the same (10,10).
here is my solution using loop
import numpy as np
arr = np.arange(36).reshape(6,6)
def suffle_section(arr, n_sections):
assert arr.shape[0]==arr.shape[1], "arr must be square"
assert arr.shape[0]%n_sections == 0, "arr size must divideable into equal n_sections"
size = arr.shape[0]//n_sections
new_arr = np.empty_like(arr)
## randomize section's row index
rand_indxes = np.random.permutation(n_sections*n_sections)
for i in range(n_sections):
## randomize section's column index
for j in range(n_sections):
rand_i = rand_indxes[i*n_sections + j]//n_sections
rand_j = rand_indxes[i*n_sections + j]%n_sections
new_arr[i*size:(i+1)*size, j*size:(j+1)*size] = \
arr[rand_i*size:(rand_i+1)*size, rand_j*size:(rand_j+1)*size]
return new_arr
result = suffle_section(arr, 3)
display(arr)
display(result)
array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23],
[24, 25, 26, 27, 28, 29],
[30, 31, 32, 33, 34, 35]])
array([[ 4, 5, 16, 17, 24, 25],
[10, 11, 22, 23, 30, 31],
[14, 15, 2, 3, 0, 1],
[20, 21, 8, 9, 6, 7],
[26, 27, 12, 13, 28, 29],
[32, 33, 18, 19, 34, 35]])
If you have access to skimage (it comes with Spyder) you could use view_as_blocks:
from skimage.util import view_as_blocks
def shuffle_tiles(arr, m, n):
a_= view_as_blocks(arr,(m,n)).reshape(-1,m,n)
# shuffle works along 1st dimension and in-place
np.random.shuffle(a_)
return a_
We will use np.random.shuffle alongwith axes permutations to achieve the desired results. There are two interpretations to it. Hence, two solutions.
Shuffle randomly within each block
Elements in each block are randomized and that same randomized order is maintaiined in all blocks.
def randomize_tiles_shuffle_within(a, M, N):
# M,N are the height and width of the blocks
m,n = a.shape
b = a.reshape(m//M,M,n//N,N).swapaxes(1,2).reshape(-1,M*N)
np.random.shuffle(b.T)
return b.reshape(m//M,n//N,M,N).swapaxes(1,2).reshape(a.shape)
Shuffle randomly blocks w.r.t each other
Blocks are randomized w.r.t each other, while keeping the order within each block same as in the original array.
def randomize_tiles_shuffle_blocks(a, M, N):
m,n = a.shape
b = a.reshape(m//M,M,n//N,N).swapaxes(1,2).reshape(-1,M*N)
np.random.shuffle(b)
return b.reshape(m//M,n//N,M,N).swapaxes(1,2).reshape(a.shape)
Sample runs -
In [47]: a
Out[47]:
array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23],
[24, 25, 26, 27, 28, 29],
[30, 31, 32, 33, 34, 35]])
In [48]: randomize_tiles_shuffle_within(a, 3, 3)
Out[48]:
array([[ 1, 7, 13, 4, 10, 16],
[14, 8, 12, 17, 11, 15],
[ 0, 6, 2, 3, 9, 5],
[19, 25, 31, 22, 28, 34],
[32, 26, 30, 35, 29, 33],
[18, 24, 20, 21, 27, 23]])
In [49]: randomize_tiles_shuffle_blocks(a, 3, 3)
Out[49]:
array([[ 3, 4, 5, 18, 19, 20],
[ 9, 10, 11, 24, 25, 26],
[15, 16, 17, 30, 31, 32],
[ 0, 1, 2, 21, 22, 23],
[ 6, 7, 8, 27, 28, 29],
[12, 13, 14, 33, 34, 35]])
Here is an approach that tries hard to avoid unnecessary copies:
import numpy as np
def f_pp(a,bs):
i,j = a.shape
k,l = bs
esh = i//k,k,j//l,l
bc = esh[::2]
sh1,sh2 = np.unravel_index(np.random.permutation(bc[0]*bc[1]),bc)
ns1,ns2 = np.unravel_index(np.arange(bc[0]*bc[1]),bc)
out = np.empty_like(a)
out.reshape(esh)[ns1,:,ns2] = a.reshape(esh)[sh1,:,sh2]
return out
Timings:
pp 0.41529153706505895
dv 1.3133141631260514
br 1.6034217830747366
Test script (continued)
# Divakar
def f_dv(a,bs):
M,N = bs
m,n = a.shape
b = a.reshape(m//M,M,n//N,N).swapaxes(1,2).reshape(-1,M*N)
np.random.shuffle(b)
return b.reshape(m//M,n//N,M,N).swapaxes(1,2).reshape(a.shape)
from skimage.util import view_as_blocks
# Brenlla shape fixed by pp
def f_br(arr,bs):
m,n = bs
a_= view_as_blocks(arr,(m,n))
sh = a_.shape
a_ = a_.reshape(-1,m,n)
# shuffle works along 1st dimension and in-place
np.random.shuffle(a_)
return a_.reshape(sh).swapaxes(1,2).reshape(arr.shape)
ex = np.arange(100000).reshape(1000,100)
bs = 10,10
tst = np.tile(np.arange(np.prod(bs)).reshape(bs),np.floor_divide(ex.shape,bs))
from timeit import timeit
for n,f in list(globals().items()):
if n.startswith('f_'):
assert (tst==f(tst,bs)).all()
print(n[2:],timeit(lambda:f(ex,bs),number=1000))
Here's code to shuffle row order but keep row items exactly as is:
import numpy as np
np.random.seed(0)
#creates a 6x6 array
a = np.random.randint(0,100,(6,6))
a
array([[44, 47, 64, 67, 67, 9],
[83, 21, 36, 87, 70, 88],
[88, 12, 58, 65, 39, 87],
[46, 88, 81, 37, 25, 77],
[72, 9, 20, 80, 69, 79],
[47, 64, 82, 99, 88, 49]])
#creates a number for each row index, 0,1,2,3,4,5
order = np.arange(6)
#shuffle index array
np.random.shuffle(order)
#make new array in shuffled order
shuffled = np.array([a[y] for y in order])
shuffled
array([[46, 88, 81, 37, 25, 77],
[88, 12, 58, 65, 39, 87],
[83, 21, 36, 87, 70, 88],
[47, 64, 82, 99, 88, 49],
[44, 47, 64, 67, 67, 9],
[72, 9, 20, 80, 69, 79]])
I need code for taking a .csv of a correlation table, sample of the table is posted here:
AA bb cc dd ff
AA 100 87 71 71 78
bb 87 100 73 74 81
cc 71 73 100 96 69
dd 71 74 96 100 71
ee 78 81 69 100 100
ff 72 73 68 68 71
Pg 68 69 62 62 64
Ph 68 69 69 62 64
Pi 68 69 62 62 64
Pj 68 69 63 63 64
Pk 70 71 65 65 67
I currently have read the .csv file with python's .csv module as a list of lists. I then removed the first column and row. And am now trying to take these int values and find the max values of each row. If there are multiple max values in a row, I want those values as well.
Then I intend to place that output into a table
file1values col row %
group1 AA AA 100
...
group1 dd ee 100
group1 ff ee 100
The issue I have so far is getting the max values for each row. Also I think I would be a bit confused on how to get the address (the col and row) for each max value.
Here is code so far:
from io import StringIO
import csv
import numpy as np
with open('/home/group1.csv', newline='') as csvfile:
reader = csv.reader(csvfile)
data_as_list = list(reader)
a = np.array(data_as_list)
a = np.delete(a, (0), axis=0)
a = np.delete(a, (0), axis=1)
np.set_printoptions(threshold=np.nan)
print (a)
print ('')
count = 0
b = (a.astype(int))
maxArr = []
while (count < b.shape[0]):
print (b[count])
count = count + 1
maxArr.append(max(b[count - 1]))
print (maxArr)
there are easier ways...
create a random matrix for tests
> import numpy as np
> m=np.random.randint(100,size=(10,10))
set diagonal to zero (or set to an out of range negative number)
> np.fill_diagonal(m,0)
array([[ 0, 35, 52, 40, 54, 1, 20, 41, 62, 92],
[45, 0, 75, 71, 85, 86, 83, 39, 52, 69],
[29, 21, 0, 78, 32, 14, 13, 27, 31, 26],
[99, 90, 16, 0, 28, 36, 30, 45, 85, 41],
[29, 21, 48, 31, 0, 86, 18, 7, 70, 76],
[96, 97, 34, 82, 51, 0, 69, 22, 27, 85],
[71, 58, 98, 42, 3, 51, 0, 19, 41, 93],
[54, 97, 86, 75, 62, 91, 78, 0, 55, 89],
[87, 44, 44, 54, 94, 94, 57, 24, 0, 81],
[94, 32, 1, 92, 34, 46, 96, 38, 75, 0]])
find the maximum values per column/row (since your matrix is symmetric doesn't matter)
> cm=np.argmax(m,1)
array([9, 5, 3, 0, 5, 1, 2, 1, 4, 6])
You will need to map the row/column indices to your labels.
> for r in range(10):
print(r,cm[r],m[r,cm[r]])
0 9 92
1 5 86
2 3 78
3 0 99
4 5 86
5 1 97
6 2 98
7 1 97
8 4 94
9 6 96
If I have output that looks like this
[[121, 120, 119, 118, 117, 116, 115, 114, 113, 112, 111],
[82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 110],
[83, 50, 49, 48, 47, 46, 45, 44, 43, 72, 109],
[84, 51, 26, 25, 24, 23, 22, 21, 42, 71, 108],
[85, 52, 27, 10, 9, 8, 7, 20, 41, 70, 107],
[86, 53, 28, 11, 2, 1, 6, 19, 40, 69, 106],
[87, 54, 29, 12, 3, 4, 5, 18, 39, 68, 105],
[88, 55, 30, 13, 14, 15, 16, 17, 38, 67, 104],
[89, 56, 31, 32, 33, 34, 35, 36, 37, 66, 103],
[90, 57, 58, 59, 60, 61, 62, 63, 64, 65, 102],
[91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101]]
how do I get it to where I can find and print a certain number and the numbers surrounding it? This is my code.
dim = 11
dx, dy = [0, 1, 0, -1], [1, 0, -1, 0]
x, y, c = 0, -1, dim**2
m = [[0 for i in range(dim)] for j in range(dim)]
for i in range(dim + dim - 1):
for j in range((dim + dim - i) // 2):
x += dx[i % 4]
y += dy[i % 4]
m[x][y] = c
c -= 1
print(m)
b = c.index(num)
print(b)
a =('\n'.join([' '.join([str(v) for v in r])for r in m]))
print(a)
Assuming that list-of-lists is called lol:-):
def neighbors(lol, anum):
for i, row in enumerate(lol[1:-1]):
try: where = row.index(anum)
except ValueError: continue
if where==0 or where==len(row)-1: continue
for j in range(i, i+3):
print(lol[j][where-1], lol[j][where], lol[j][where+1])
print()
This embodies several assumptions, such as: (A) you don't care for hits on the first or last row or column since they don't have all the neighbors you want to print, and also (B) you don't care about multiple "hits" in a single row but (C) do care about "hits" in multiple rows.
Of course all such assumptions can be changed but that requires you to be much more precise in your specs than you've been so far:-).
The print format assumes either Python 3 or a from __future__ import print_function if you're stuck with Python 2.
First in this case as c is a int value hasn't attribute index . so the following command will raise an AttributeError .
b = c.index(num)
and for get the desire result all that you need here is reversing the r list in following command , and for print you can use format :
a =('\n'.join([' '.join(["{:3}".format(v) for v in r[::-1]])for r in m]))
so the result will be :
111 112 113 114 115 116 117 118 119 120 121
110 73 74 75 76 77 78 79 80 81 82
109 72 43 44 45 46 47 48 49 50 83
108 71 42 21 22 23 24 25 26 51 84
107 70 41 20 7 8 9 10 27 52 85
106 69 40 19 6 1 2 11 28 53 86
105 68 39 18 5 4 3 12 29 54 87
104 67 38 17 16 15 14 13 30 55 88
103 66 37 36 35 34 33 32 31 56 89
102 65 64 63 62 61 60 59 58 57 90
101 100 99 98 97 96 95 94 93 92 91