Is there a way to stack JaggedArrays without fromiter()? - awkward-array

I have two 2D JaggedArrays of the same length (in axis=0) that I'd like to stack in axis=1. For example:
a = awkward.fromiter([[0], [3, 4]])
b = awkward.fromiter([[1, 2], [5]])
and I want to get this JaggedArray:
[ [ [0], [1, 2] ],
[ [3, 4], [5] ] ]
I can get exactly this with the following:
awkward.fromiter(np.stack([a, b], axis=1))
but is there a way to accomplish this directly in awkward, without having to use fromiter() on nested numpy arrays?

Related

Algorithm to check if a multidimensional array contains another?

Say I have two multidimensional arrays of equal depth, say:
[ [1, 2, 3],
[4, 5, 6],
[7, 8, 9] ]
and
[ [2, 3],
[5, 6] ]
What sort of algorithm can I follow to determine if the latter is a contiguous subarray of the former?
For example, with the above example, it is:
And also with this pair of 3d arrays:
[ [ [4, 6],
[5, 7] ],
[ [2, 8],
[9, 3] ] ]
[ [ [4, 6] ],
[ [2, 8] ] ]
Another way of interpreting this is that by removing the first or last item from a dimension of the first array repeatedly, you will eventually get the target array.
The Rabin-Karp string search algorithm can be extended to multiple dimensions to solve this problem.
Lets say your pattern array is M rows by N columns:
Using any rolling hash function, like a polynomial hash, first replace every column of your pattern array with the hash of the column, reducing it to 1 dimension. Then hash the remaining row. This will be your pattern hash.
Now use the rolling hash in your target array to replace all values in rows >= M by the hash of those values with the M-1 values above them.
Then, similarly replace all remaining values in columns >= N-1 with the hash of those values and the N-1 values to the left.
Finally, find any instances of the pattern hash in the resulting matrix. When you find one, compare with your pattern array to see if it's a real match.
This algorithm extends to as many dimensions as you like and, like simple Rabin-Karp, it takes O(N) expected time if the number of dimensions is constant.
The simple and naive approach would be, to look for first (0,0) match and then to compare the sub array.
Example: (Python)
hay=[ [1, 2, 3],
[4, 5, 6],
[7, 8, 9] ]
needle=[ [2, 3],
[5, 6] ]
def get_sub_array(array,i,j,width,height):
sub_array=[]
for n in range(i,i+height):
sub_array.append(array[n][j:j+width])
return sub_array
def compare(arr1,arr2):
for i in range(len(arr1)):
for j in range(len(arr1[0])):
if arr1[i][j]!=arr2[i][j]:
return False
return True
def is_sub_array(hay,needle):
hay_width=len(hay[0])
hay_height=len(hay)
needle_width=len(needle[0])
needle_height=len(needle)
for i in range(hay_height-needle_height+1):
for j in range(hay_width-needle_width+1):
if hay[i][j]==needle[0][0]:
if compare(
get_sub_array(hay,i,j,needle_width,needle_height),
needle
):
return True
return False
print(is_sub_array(hay,needle))
Output:
True

How to eliminate the rows from an array which have common elements at different index position in python?

I have a 2D array of form
[[ 1 6]
[ 2 7]
[ 5 6]
[ 6 1]
[ 6 5]
[ 7 2]]
I want the output of the form
[[ 1 6]
[ 2 7]
[ 5 6]]
How I can get this output?
Here's a solution using plain Python, but I'm sure there's a more idiomatic way with NumPy.
import numpy as np
a = np.array([
[1, 6],
[2, 7],
[5, 6],
[6, 1],
[6, 5],
[7, 2]])
seen = set()
out = []
for row in a:
elements = frozenset(row)
if elements not in seen:
seen.add(elements)
out.append(row)
print(np.array(out))
Output:
[[1 6]
[2 7]
[5 6]]

Julia: counting total number of elements in an array-of-arrays

Is there a single function in Julia that will give you the total number of elements in an array-of-arrays (or 'jagged array')?
Here's what I mean:
my_array_of_arrays = [ [1, 5], [6], [10, 10, 11] ]
I'm looking for a function such that
desired_function(my_array_of_arrays) will return 6
And if not, what's the quickest way to do this in Julia?
Thanks in advance!
One way to do it without additional dependencies would be to use sum:
julia> my_array_of_arrays = [ [1, 5], [6], [10, 10, 11] ]
3-element Array{Array{Int64,1},1}:
[1, 5]
[6]
[10, 10, 11]
julia> sum(length, my_array_of_arrays)
6
However, if you want to work more intensively with ragged arrays, you might be better off using specialized packages, such as ArraysOfArrays.jl.
sum(length, x) suggested by #MattB is a more elegant answer and it deserves being here so others can find it.
Testing:
julia> my_array_of_arrays = [ [1, 5], [6], [10, 10, 11] ]
3-element Array{Array{Int64,1},1}:
[1, 5]
[6]
[10, 10, 11]
julia> sum(length, my_array_of_arrays)
6
Note that the performance of both methods mapreduce(length, +, x) and sum(length, x) is identical since both do not materialize the data.

Can someone explain in detail how mapping this array works step by step

The original array: [ [3, 5], [9, 6], [3,1] ]
1) Make the first number in each mini array the smaller number and the second number in each mini array the bigger number
- [ [3, 5], [9, 6], [3,1] ] -> [[ 3,5], [6,9], [1,3]]
2) Sort the mini arrays by first number.
- [ [3,5], [6,9], [1,3] ] -> [ [1,3], [3,5], [6,9] ]
So [ [3, 5], [9, 6], [3,1] ] -> [ [1,3], [3,5], [6,9] ] by the end of the sorting transformation.
Can someone explain in a step by step, detailed, clear, concise way how to use array.map() to make this happen?
Use map to make the nested array numbers placed in increasing order, then apply sort based on first number in the nested array.
const arr = [
[3, 5],
[9, 6],
[3, 1]
];
const sortedArr = arr
.map(([num1, num2]) => num2 < num1 ? [num2, num1] : [num1, num2])
.sort(([arr1num1], [arr2num1]) => arr1num1 - arr2num1);
console.log(sortedArr);
-- Edit--
Result of map
[[3, 5], [6, 9], [1, 3]];
In the sort function, I'am doing array destructuring (see - https://javascript.info/destructuring-assignment). Basically, I'am only extracting the first element from array and storing in separate variable. In our case, arr1num1 and arr2num1.
Example-
const arr = [3, 5];
// Extracting the first element from array and saving in variable - arr1num1.
// I do not need second array element 5, so i did not extracted the second array element
const [arr1num1] = arr; // arr1num1 will have now value 3
console.log(arr1num1);
// If second array element is also required, then the above statement will become const [num1, num2] = arr; where num1 -> 3 and num2 ->5
Alternative, to above would be to directly access array elements using there index.
const arr = [
[3, 5],
[9, 6],
[3, 1]
];
const sortedArr = arr
.map(([num1, num2]) => num2 < num1 ? [num2, num1] : [num1, num2])
.sort((arr1, arr2) => arr1[0] - arr2[0]);
console.log(sortedArr);
To know more about sort, see - Sorting
How sorting works,
In first iteration, swapping of [3, 5] & [6, 9] will happen based on sort condition.
arr1num1 -> 3
arr2num1 -> 6
The statement arr1num1 - arr2num1 will check if 3 is greater than 6. If yes, it will swap the arrays [3, 5] and [6, 9]. Since, 3 is not greater than 9, so no swapping will take place.
Second Iteration, swapping of [6, 9] and [1, 3] will take place based on condition.
arr1num1 -> 6
arr1num2 -> 1
Since, 6 > than 1, swapping will take place.
Before Swapping array will be- `[[3, 5], [6, 9], [1, 3]]`;
After Swapping array will be - `[[3, 5], [1, 3], [6, 9]]`;
This process will continue, until your array gets sorted.

Appending pairs of coordinates to numpy array

I need to append 1D arrays (coordinates) into a 2d array using numpy in python 3.6.
I can do this with lists using append, such as in the first example below.
mastlist =[]
i=0
for i in range (10):
i=i+1
coor = []
xcoor = i
ycoor =i*2
coor.append(xcoor)
coor.append(ycoor)
mastlist.append(coor)
print(mastlist)
But I want a more performant approach using numpy arrays. When I attempt to convert the list approach to an array (second example),
import numpy as np
i=0
for i in range (10):
i=i+1
centroid =np.append(i,i*2)
masterarray=np.append([centroid],axis=0)
print(masterarray)
print(masterarray)
I get the error below.
My error is:
TypeError: append() missing 1 required positional argument: 'values'
I would of expected an array such as:
[[1, 2], [2, 4], [3, 6], [4, 8], [5, 10], [6, 12], [7, 14], [8, 16], [9, 18], [10, 20]]
I have also fumbled with attempts using extend, vstack, and concatenate.
Any advice would be welcome.
I recommend you get single coordinate data firstly , then concatenate them. To my best knowledge, I dont think it can be done by np.append
The common method is np.concatenate, which I see it from cs231n class.
My sample codes are as follows:
import numpy as np
xcoor = np.arange(1,11,1).reshape(-1,1)
ycoor = np.arange(2,22,2).reshape(-1,1)
xycoor = np.concatenate((xcoor,ycoor),axis = 1)
print(xycoor)
Output:
[[ 1 2]
[ 2 4]
[ 3 6]
[ 4 8]
[ 5 10]
[ 6 12]
[ 7 14]
[ 8 16]
[ 9 18]
[10 20]]
Why not just use list comprehension?
import numpy as np
masterarray = np.array([[i,2*i] for i in range(1,11)])
output
array([[ 1, 2],
[ 2, 4],
[ 3, 6],
[ 4, 8],
[ 5, 10],
[ 6, 12],
[ 7, 14],
[ 8, 16],
[ 9, 18],
[10, 20]])

Resources