I need to save a 2D array representing a map in the game world to a configparser. The data looks like this:
[[0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 0]]
As an example.
I can obviously save the data but I can't convert it from a string back to a list after reading it back in...
I don't mind if I have to use a .txt file instead, by the way, and just read it in with the normal text file handler.
Python has a module for saving Python data called pickle. You can use that. From the docs:
The pickle module implements a fundamental, but powerful algorithm for
serializing and de-serializing a Python object structure. “Pickling”
is the process whereby a Python object hierarchy is converted into a
byte stream, and “unpickling” is the inverse operation, whereby a byte
stream is converted back into an object hierarchy. Pickling (and
unpickling) is alternatively known as “serialization”, “marshalling,”
or “flattening”, however, to avoid confusion, the terms used here
are “pickling” and “unpickling”.
Demo:
>>> import pickle
>>> data = [[0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 0]]
>>> with open('C:/temp/pickle_test.data', 'wb') as f:
pickle.dump(data, f)
>>> with open('C:/temp/pickle_test.data', 'rb') as f:
new_data = pickle.load(f)
>>> new_data
[[0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 0]]
You can do it using a simple eval
>>> x="[[0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 0]]"
>>> type(x);
<type 'str'>
>>> y=eval(x);
>>> print(y);
[[0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 0]]
>>>type(y);
<type 'list'>
It's a very quick and dirty solution, you should use more secure and good input files parsers (like pickle).
For the transformation of a string to a list you could do something like this:
myList = [x for x in "0,1,2,3".split(",")]
type(myList)
<type 'list'>
print myList
['0', '1', '2', '3']
Related
So I have a nested list of 3 x 3 matrices like
a = [ [[1,0,3],[0,1,2],[-1,4,-8]], ... ]
And I am trying to find an efficient way to convert it to a list that Mathematica can read. In this case I was thinking of converting a to a string and replacing each [ with {, and each ] with }, then saving this string to a file. My guess is that is not the most efficient method.
Are there any suggestions for an efficient algorithm to convert from python nested arrays to mathematica arrays?
Make it as numpy.array and flatten it:
import numpy as np
arr = [[[0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]]
np.array(arr).flatten()
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0])
Or if you prefer list, add tolist():
np.array(arr).flatten().tolist()
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0]
As a general rule, if you are worried about the efficiency of reading/writing files you should be reading/writing binary data. Conversely, if you are committed to text files don't worry overmuch about efficiency.
I see nothing materially wrong in your proposal to write the nested arrays to a string and then replace the brackets with the ones that Mathematica likes.
Personally, though, if the nested array is regular, and if we're sticking with text files, I'd suggest writing a file with:
a header line containing the extents of each dimension of the nested array, for your example this might be 3, 3, ... (or possibly ..., 3, 3)
and then writing the numbers 3 to a line for as many lines as necessary
If the nested array is not regular you might want to devise a more complex header line to tell Mathematica how to ravel the following numbers. But whatever you do, keep it simple.
You might be able to do better using Mathematica's recent ExternalEvaluate["Python", ...] capability and avoid file-writing and reading. But this is not something I have experience of to pass along.
You may use Import with either "JSON" or "BSON" or "PythonExpression" to import the data from a file. Either of these can be directly exported by Python.
Wolfram Language (a.k.a. Mathematica) can import and export many formats with the above being some of the Basic Formats it supports.
Hope this helps.
This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 7 years ago.
s is a list of lists of integers with all values initialized to zero. I would like to increment only the first element of the first row by one, but the following command increments the first element of every row by one. How may I achieve this?
In [6]: s = [[0]*4]*4
In [7]: s[0][0] += 1
In [8]: s
Out[8]:
[[1, 0, 0, 0, 0],
[1, 0, 0, 0, 0],
[1, 0, 0, 0, 0],
[1, 0, 0, 0, 0],
[1, 0, 0, 0, 0]]
Okay! Thanks for the advice, the problem was in my construction of s.
If s is truly a list of lists (and not a list containing multiple references to the same list), what you did works, your issue must be elsewhere
>>> s = [[0, 0, 0, 0, 0],
... [0, 0, 0, 0, 0],
... [0, 0, 0, 0, 0],
... [0, 0, 0, 0, 0],
... [0, 0, 0, 0, 0]]
>>> s[0][0]
0
>>> s[0][0] = 1
>>> s
[[1, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
You made your lists "incorrectly" in the first place; each element of your list simply points to the same single list. When you update that list they all update.
Make the list of lists using code something like this instead:
s = [[0 for _ in range(5)] for _ in range(5)]
This is classical Python oversight since lists assignments are done by references not by deep copy.
For example if you constructed using this way that's where it would have gone wrong.
>>> zeros = [0,0,0,0]
>>> s = [zeros,zeros,zeros,zeros]
>>> s[0][0]+=1
>>> s
[[1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]]
So while copying lists use as below
>>> s = [list(zeros), list(zeros), list(zeros), list(zeros)]
>>> s[0][0]+=1
>>> s
[[1, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
I have a list of ground truth labels:
yTrue = ['class2','classC','class3','class3','classA','classB','class2']
and a list of the possible classes (distinct, in custom order):
orderedClasses = ['classA','class2','classB','class3','classC']
I want to code the list in One-Vs-The-Rest for all possible classes.
Desired output:
[[0,1,0,0,0],[0,0,0,0,1],[0,0,0,1,0],[0,0,0,1,0],[1,0,0,0,0],[0,0,1,0,0],[0,1,0,0,0]]
I tried to use sklearn.preprocessing.label_binarize (doc) but the problem is it doesn't maintain my custom order for classes:
[[0,0,1,0,0],[0,0,0,0,1],[1,0,0,0,0],[1,0,0,0,0],[0,0,0,1,0],[0,1,0,0,0],[0,0,1,0,0]]
Looking for an Pythonic and efficient way to get the desired output
Simply pass orderedClasses as classes parameter
In [15]: label_binarize(yTrue, orderedClasses)
Out[15]:
array([[0, 1, 0, 0, 0],
[0, 0, 0, 0, 1],
[0, 0, 0, 1, 0],
[0, 0, 0, 1, 0],
[1, 0, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 1, 0, 0, 0]])
I have the following matrix generated:
matrix = [[0] * columns for i in range(rows)]
where the user defines the rows and columns in the main sequence.
Say the user entered the numbers such that rows = 5 and columns = 4. When I print the matrix, I will get the following:
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
Thats okay, but I would like to make it nicer, so that it would look like this:
[
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]
]
I believe that you would need to use something like \n, but I'm having trouble as to how to implement it. Perhaps theres a built-in function alread that I don't know of? Any help would be appreciated.
def formattedPrint(matrix):
print "["
for i in matrix:
print(i)
print "]"
You can take a look at the pprint library built into Python. I use it in 2.7, but it is available in Python 3.
I have to create a matrix (or an array) from a string file like this:
>>>print Qval
[1*10**4,0,0,0],[0,1,0,0],[0,0,1*10**3,0], [0,0,0,1]
>>>print type(Qval)
<type 'str'>
I have to get the matrix this way, because in my Tkinter GUI I have to input the value like this (part of the interface: field label= default value):
Q-Matrix= [1*10**4,0,0,0],[0,1,0,0],[0,0,1*10**3,0],[0,0,0,1]
I get the Qval string from my interface like this:
Qval=vars[13].get()
Is there a proper way to do this?
Thanks.
>>> ast.literal_eval('[1e4, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1e3, 0], [0, 0, 0, 1]')
([10000.0, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1000.0, 0], [0, 0, 0, 1])
you can use the built-in function eval like that:
a ="[1*10**4,0,0,0],[0,1,0,0],[0,0,1*10**3,0], [0,0,0,1]"
mat = eval(a)