Whitespaces after addition to numpy array - python

Why when I'm executing code below I get those weird whitespaces in output?
import numpy as np
str = 'a a b c a a d a g a'
string_array = np.array(str.split(" "))
char_indices = np.where(string_array == 'a')
array = char_indices[0]
print(array)
array += 2
print(array)
output:
[0 1 4 5 7 9]
[ 2 3 6 7 9 11]

That's just numpy's way of displaying data to make it appear aligned and more readable.
The alignment between your two lists changes
[0 1 4 5 7 9]
[ 2 3 6 7 9 11]
because there is a two-digit element in the second list.
In vectors it is more difficult to appreciate, but it is very useful when we have more dimensions:
>>> a = np.random.uniform(0,1,(5,5))
>>> a[a>0.5] = 0
>>> print(a)
[[0. 0. 0.00460074 0.22880318 0.46584641]
[0.0455245 0. 0. 0. 0. ]
[0. 0.07891556 0.21795357 0.14944522 0.20732431]
[0. 0. 0. 0.3381172 0.08182367]
[0. 0. 0.10734559 0. 0.31228533]]
>>> print(a.tolist())
[[0.0, 0.0, 0.0046007414146133074, 0.22880318354923768, 0.4658464110307319], [0.04552450444387102, 0.0, 0.0, 0.0, 0.0], [0.0, 0.07891556038021574, 0.21795356574892966, 0.1494452184954096, 0.2073243102108967], [0.0, 0.0, 0.0, 0.33811719550156627, 0.08182367499758836], [0.0, 0.0, 0.10734558995972832, 0.0, 0.31228532775003903]]

Related

How to create a networkx Graph using 2D np array as input

My algorithm outputs the set of vertices describing objects in 3D space (x, y, z). In this case, there are two objects:
verts =
[[0.1 1. 1. ] [1. 1. 0.1] [1. 0.1 1. ] [1. 1. 1.9] [1. 1.9 1. ]
[1.9 1. 1. ] [7.1 8. 8. ] [8. 8. 7.1] [8. 7.1 8. ] [8. 8. 8.9]
[8. 8.9 8. ] [8.9 8. 8. ]]
There are two tetrahedrons, one confined between centered on (1, 1, 1), the other on (8, 8, 8). My goal is to use breadth-first search to identify that the objects are separate, and then classify each. I have not been able to get the data in the correct form for my algorithm.
Instead, I intend to use the networkx module, specifically using the Graph class, which takes ndarrays as input. I have tried:
import networkx as nx
import numpy as np
graph = Graph(verts)
for idx, graph in enumerate(nx.connected_components(graph)):
print("Graph ",idx, " in ", graph,'\n\n',file=open("output.txt","a"))
However, I cannot create graph. Instead, I get the error:
"Input is not a correct numpy matrix or array.")
networkx.exception.NetworkXError: Input is not a correct numpy matrix or array.
This confuses me because type of verts = numpy.ndarray.
I am open to either using networkx for this task, or developing some other strategy. Additionally, please let me know if there are any edits that might make this post more clear.
Edit: One thing that may help is another output, faces. These 'define triangular faces via referencing vertex indices from verts.' I believe these can be used to 'connect' or draw lines from vertex to vertex, eventually to create a dictionary.
faces =
[[ 2 1 0] [ 0 3 2] [ 1 4 0] [ 0 4 3] [ 5 1 2] [ 3 5 2]
[ 5 4 1] [ 4 5 3] [ 8 7 6] [ 6 9 8] [ 7 10 6] [ 6 10 9]
[11 7 8] [ 9 11 8] [11 10 7] [10 11 9]]
A method has been proposed, and it works for this set of data. However, it does not work for all. This edit uploads a new set of data.
verts =
[[0.1 1. 1. ] [1. 1. 0.1] [1. 0.1 1. ] [1. 1. 1.9] [1. 1.9 1. ] [1.9 1. 1. ]
[3.1 1. 4. ] [4. 1. 3.1] [4. 0.1 4. ] [4. 1. 4.9] [4. 1.9 4. ] [5. 1. 3.1]
[5. 0.1 4. ] [5. 1. 4.9] [5. 1.9 4. ] [5.9 1. 4. ] [7.1 8. 8. ]
[8. 8. 7.1] [8. 7.1 8. ] [8. 8. 8.9] [8. 8.9 8. ] [9. 8. 7.1]
[9. 7.1 8. ] [9. 8. 8.9] [9. 8.9 8. ] [9.9 8. 8. ]]
And it looks like this.
I was able to answer this by another approach. It is lengthy because I need to include extra pieces. As a general outlook, I solved this problem by utilizing faces, which defines each triangle with the indices of its vertices. faces tells me which vertices are connected. This allowed me to build a linelist, which contains all of the connections between vertices.
# using faces and verts in original post
linelist = []
for idx, vert in enumerate(faces):
print(vert)
for i,x in enumerate(vert):
l = [np.ndarray.tolist(verts[faces[idx][i]]), np.ndarray.tolist(verts[faces[idx][(i+1)%len(vert)]])]
linelist.append(l)
Which yields elements like:
[[1.0, 0.10000000149011612, 1.0], [1.0, 1.0, 0.10000000149011612]]
Edit: Discovered faster method:
tmp = [tuple(tuple(j) for j in i) for i in linelist]
graph = nx.Graph(tmp)
graphs = []
i=0
open('output.txt','w').close()
for idx, graph in enumerate(nx.connected_components(graph)):
graphs.append(graph)
print("Graph ",idx," corresponds to vertices: ",graph,'\n\n',file=open("output.txt","a"))
i+=1
These points are connected. Next, I used someone else's code to create a dictionary where each key is a vertex and each value is a connected vertex. And then I used breath-first-search on this dictionary. See the class below.
class MS_Graph():
def __init__ (self, linelist=None, vertices=None):
self.linelist = linelist if linelist is not None else None
self.vertices = vertices if vertices is not None else None
def getGraph(self):
'''
Takes self.linelist and converts to dict
'''
linelist = self.linelist
# edge list usually reads v1 -> v2
graph = {}
# however these are lines so symmetry is assumed
for l in linelist:
v1, v2 = map(tuple, l)
graph[v1] = graph.get(v1, ()) + (v2,)
graph[v2] = graph.get(v2, ()) + (v1,)
return graph
def BFS(self, graph):
"""
Implement breadth-first search
"""
# get nodes
#nodes = list(graph.keys()) # changed 4/16/2020
nodes = list(graph)
graphs = []
# check all nodes
while nodes:
# initialize BFS
toCheck = [nodes[0]]
discovered = []
# run bfs
while toCheck:
startNode = toCheck.pop()
for neighbor in graph.get(startNode):
if neighbor not in discovered:
discovered.append(neighbor)
toCheck.append(neighbor)
nodes.remove(neighbor)
# add discovered graphs
graphs.append(discovered)
self.graphs = graphs
return graphs
And, bringing it altogether:
Graph = MS_Graph(linelist)
graph = Graph.getGraph()
graphs = Graph.BFS(graph)
print(len(graphs))
# output: 3
print(graphs)
# output:
[[(1.0, 1.0, 0.10000000149011612), (0.10000000149011612, 1.0, 1.0), (1.0, 1.0, 1.899999976158142), (1.899999976158142, 1.0, 1.0), (1.0, 0.10000000149011612, 1.0), (1.0, 1.899999976158142, 1.0)],
[(4.0, 1.0, 3.0999999046325684), (3.0999999046325684, 1.0, 4.0), (4.0, 1.0, 4.900000095367432), (5.0, 1.0, 3.0999999046325684), (5.0, 0.10000000149011612, 4.0), (4.0, 0.10000000149011612, 4.0), (5.0, 1.0, 4.900000095367432), (5.900000095367432, 1.0, 4.0), (5.0, 1.899999976158142, 4.0), (4.0, 1.899999976158142, 4.0)],
[(8.0, 8.0, 7.099999904632568), (7.099999904632568, 8.0, 8.0), (8.0, 8.0, 8.899999618530273), (8.899999618530273, 8.0, 8.0), (8.0, 7.099999904632568, 8.0), (8.0, 8.899999618530273, 8.0)]]
That said, I do wonder if there is a faster method.
Edit: There may be a faster way. Since faces contains the vertices of every single triangle, all triangles that belong to one object will have an unbroken chain. i.e. the set of vertices composing object 1 will be distinct from the set of vertices composing any other object.
For example the set of faces for each object:
object_1_faces =
[ 2 1 0]
[ 0 3 2]
[ 1 4 0]
[ 0 4 3]
[ 5 1 2]
[ 3 5 2]
[ 5 4 1]
[ 4 5 3]
object_2_faces =
[ 8 7 6]
[ 6 9 8]
[ 7 10 6]
[ 6 10 9]
[11 7 8]
[ 9 11 8]
[11 10 7]
[10 11 9]
object_1_vertices = {0,1,2,3,4,5}
object_2_vertices = {6,7,8,9,10,11}
I imagine this means there is a faster way than finding all of the lines.
The problem is how you're constructing the graph. You should first create a new instance of a graph with g = nx.Graph(), and then use its methods to either add its nodes or edges. In this case, you want to add its paths from the nested list:
G = nx.Graph()
for path in verts:
nx.add_path(G, path)
And then obtain the connected components:
cc = list(nx.connected_components(G))
# [{0.1, 1.0, 1.9}, {7.1, 8.0, 8.9}]
Now if you wanted to find which component each path belongs to, you could iterate over the paths and check with which of the components they intersect:
from collections import defaultdict
subgraphs = defaultdict(list)
for path in verts:
for ix,c in enumerate(cc):
if c.intersection(path):
subgraphs[ix].append(path)
print(subgraphs)
defaultdict(list,
{0: [[0.1, 1.0, 1.0],
[1.0, 1.0, 0.1],
[1.0, 0.1, 1.0],
[1.0, 1.0, 1.9],
[1.0, 1.9, 1.0],
[1.9, 1.0, 1.0]],
1: [[7.1, 8.0, 8.0],
[8.0, 8.0, 7.1],
[8.0, 7.1, 8.0],
[8.0, 8.0, 8.9],
[8.0, 8.9, 8.0],
[8.9, 8.0, 8.0]]})

Python - Generate random real number between range with a step size

I am using python-3.x, and I am trying to generate an initial population that contains random real numbers between 0 and 1 where these numbers should be one of the following:
0, 0.33333, 0.666667 or 1
That means the difference between these numbers is 0.33333 (1/3). I tried to modify this code in many ways but their no luck
import numpy as np
import random
from random import randint
from itertools import product
pop_size = 7
i_length = 2
i_min = 0
i_max = 1
level = 2
step = ((1/((2**level)-1))*(i_max-i_min))
def individual(length, min, max):
return [ randint(min,max) for x in range(length) ]
def population(count, length, min, max):
return [ individual(length, min, max) for x in range(count) ]
population = population(pop_size, i_length, i_min, i_max)
##count: the number of individuals in the population
##length: the number of values per individual
##min: the minimum possible value in an individual's list of values
##max: the maximum possible value in an individual's list of values
##this code was taken from :https://lethain.com/genetic-algorithms-cool-name-damn-simple/
I did this lines which works very well for me:
population2 = np.array(list(product(np.linspace(i_min, i_max, 2**level), repeat=2)))
population3 = [j for j in product(np.arange(i_min, i_max+step, step), repeat=2)]
but the problem it will list all the possible values which are not what I want. I want random numbers where the population size will be given
the result I want to see is smailar to (numpy array or list):
population = [[0, 1],
[0, 0.3333],
[0.3333, 1],
[1, 0.6667],
[0.3333, 0.6667],
[0.6667, 0],
[0.3333, 0.3333]]
keep in mind the:
level = 2
where I can calculat the the step value:
step = ((1/((2**level)-1))*(i_max-i_min))
for example, if I changed the level = 2 to level = 3 then it is no more using the 0.3333 it will change to 0.1428 1/7) which I will get different values.
Any advice would be much appreciated
>>> np.random.choice([0, 1/3., 2/3., 1], size=(7,2), replace=True)
array([[0. , 0.33333333],
[0.33333333, 0.66666667],
[0. , 0. ],
[0.66666667, 0. ],
[0.33333333, 0.33333333],
[1. , 1. ],
[0.33333333, 0.33333333]])
>>> i_min = 0
>>> i_max = 1
>>> level = 3
>>> np.random.choice(np.linspace(i_min, i_max, 2**level), size=(7,2), replace=True)
array([[0.28571429, 0.14285714],
[0.85714286, 0.57142857],
[0.71428571, 0.42857143],
[0.71428571, 1. ],
[0.14285714, 0.85714286],
[0. , 0. ],
[1. , 0. ]])
Without numpy:
from random import randint
def get_population(num, repeats, fraction):
return [[randint(0, fraction)/fraction for x in range(num)] for i in range(repeats)]
print(get_population(2, 7, 3))
Output is:
[[0.3333333333333333, 0.0],
[0.3333333333333333, 1.0],
[1.0, 0.3333333333333333],
[0.3333333333333333, 0.0],
[0.0, 0.3333333333333333],
[0.3333333333333333, 0.6666666666666666],
[1.0, 1.0]]
Fraction 7:
print(get_population(2, 7, 7))
Output is:
[[0.8571428571428571, 0.7142857142857143],
[0.7142857142857143, 0.14285714285714285],
[0.0, 0.7142857142857143],
[0.42857142857142855, 0.5714285714285714],
[0.42857142857142855, 0.7142857142857143],
[1.0, 0.5714285714285714],
[1.0, 1.0]]

Python - Break numpy array into positive and negative components

I have numpy arrays of shape (600,600,3), where the values are [-1.0, 1.0]. I would like to expand the array to (600,600,6), where the original values are split into the amounts above and below 0. Some examples (1,1,3) arrays, where th function foo() does the trick:
>>> a = [-0.5, 0.2, 0.9]
>>> foo(a)
[0.0, 0.5, 0.2, 0.0, 0.9, 0.0] # [positive component, negative component, ...]
>>> b = [1.0, 0.0, -0.3] # notice the behavior of 0.0
>>> foo(b)
[1.0, 0.0, 0.0, 0.0, 0.0, 0.3]
Use slicing to assign the min/max to different parts of the output array
In [33]: a = np.around(np.random.random((2,2,3))-0.5, 1)
In [34]: a
Out[34]:
array([[[-0.1, 0.3, 0.3],
[ 0.3, -0.2, -0.1]],
[[-0. , -0.2, 0.3],
[-0.1, -0. , 0.1]]])
In [35]: out = np.zeros((2,2,6))
In [36]: out[:,:,::2] = np.maximum(a, 0)
In [37]: out[:,:,1::2] = np.maximum(-a, 0)
In [38]: out
Out[38]:
array([[[ 0. , 0.1, 0.3, 0. , 0.3, 0. ],
[ 0.3, 0. , 0. , 0.2, 0. , 0.1]],
[[-0. , 0. , 0. , 0.2, 0.3, 0. ],
[ 0. , 0.1, -0. , 0. , 0.1, 0. ]]])

Python: How to convert multiple list that have multiple digits into array?

I have a text file with listed 4 x 3 binary values as such:
1 0 1
0 0 1
1 1 0
0 0 1
When I read this file in python, it is in this form:
import numpy as np
with open("test.txt")as g:
p=g.read().splitlines()
q=[];
for m in p:
q.append(int(m));
p=q;
Python window:
>>> p
['1 0 1', '0 0 1', '1 1 0', '0 0 1']
How to convert it into array:
array([[ 1.0, 0.0, 1.0],
[ 0.0, 0.0, 1.0],
[ 1.0, 1.0, 0.0],
[ 0.0, 0.0, 1.0]])
The simplest solution by far is to skip all the intermediate steps of reading the file of your own and converting the lines to lists of lists and just use numpy.loadtxt(). The values will be of float type by default, so you won't have to do anything more.
import numpy as np
dat = np.loadtxt('test.txt')
You can loop over each line of p, split the string into separate numbers and, finally, convert each substring into a float:
import numpy as np
p = ['1 0 1', '0 0 1', '1 1 0', '0 0 1']
print np.array([map(float, line.split()) for line in p])
Output:
[[ 1. 0. 1.]
[ 0. 0. 1.]
[ 1. 1. 0.]
[ 0. 0. 1.]]
Assuming you're guaranteed a sane enough input you can split the strings and convert the fragments to int:
def str2ints(l):
return [int(frag) for frag in l.split()]
This function takes one line and splits it into parts, fx "1 0 1" are split into ["1", "0", "1"] then I use list comprehension and converts the fragments to an int.
You use more of list comprehension to do it on the entire p:
[str2ints(l) for l in p]

4 x 4 Floats to numpy Matrix

Following numpy command:
c = np.matrix('1,0,0,0;0,1,0,0;0,0,1,0;-6.6,1.0,-2.8, 1.0')
creates a matrix Outupt:
[[ 1. 0. 0. 0. ]
[ 0. 1. 0. 0. ]
[ 0. 0. 1. 0. ]
[-6.6 1. -2.8 1. ]]
However my Input is a comma-separated array of floats :
[1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, -6.604560409595856, 1.0, -2.81542864114781, 1.0]
Is there a simple way of getting those floats, easily into a numpy matrix by defining the shape in before as a 4 x 4 matrix?
np.array([1.0, 0.0,..., -2.81542864114781, 1.0]).reshape((4, 4))

Categories