pythonarraysnumpytext-widget

How to obtain an array of an array (ndarray) from the input of a text widget?


I have a text widget where the user has to enter input in this form:

a 1 b 2 c 3
d 4 e 5 f 6
g 7 h 8 i 9

And I want this input to be converted to an array of an array (ndarray) where each line is one array in which I can get each item separately:

[1 2 3], [4 5 6], [7 8 9]

What I tried so far:

The characters are important for later use but for now I only need the numbers. I managed to save the input as an array and getting another array out of this containing only the numbers. What I then need is to cut the input in certain equal pieces (in this example three). I found out that one can use the np.split function for this but has to convert the array to either an integer or 1D-array first.

I know that in the case for an integer I can use processed_input_3 = np.split(processed_input_2, [3]) and the list is separated into three equal parts (as I understood to get a ndarray). In the case of a 1D-array the list is separated in dependence of some axis.

When I enter the input into the text widget and click the "Go"-button the program returns [array([1, 2, 3]), array([4, 5, 6, 7, 8, 9])]. This looks like I created a 1D-array instead of an integer. My problem is that I neither understand the difference between an integer and a 1D-array nor the concept of the axis in the case of a 1D-array.

import tkinter as tk
import numpy as np

root = tk.Tk()

processed_input = []

def process_data():
    input_values = np.array(input_text.get("1.0", "end-1c").split()) # saves input as array

    for x in input_values[1::2]: # getting every second item starting from index #1, so only the numbers
        processed_input.append(x) # saves the only numbers containing array

    processed_input_2 = np.array(processed_input , dtype="int") # converts array to integer
    processed_input_3 = np.split(processed_input_2, [3])

    print(processed_input_2)
    print(processed_input_3)

input_text = tk.Text(root)
go_button = tk.Button(root, command=process_data, text="Go")

input_text.grid(row=0, column=0)
go_button.grid(row=1, column=0)

root.mainloop()

Solution

  • I feel like you try to do too many things at once, in the opposite direction of the natural order. I should also mention that a numpy array only make sense if you do numerical computation with it and use some numerical type, but as long as you're manipulating strings lists, changing their length etc it's worth sticking to lists. So I'd rewrite your function as follows: To eliminate the need for splitting up the array into chunks in the end, I'd first use splitlines() and then use split(' ') on these, to automatically get the right structure. By using a list comprehension you can then easily conver the strings containing the integers into actual integers. As soon as you have a non-ragged list of lists of numers, you can convert it to a numpy array. In my opinion it doesn't make sense to convert it any earlier, as they cannot be shrunk or expanded like python lists, it will always create a new object.

    def process_data():
        lines = input_text.get("1.0", "end-1c").splitlines()  # extract lines
        values = [[int(v) for v in l.split(' ')[1::2]] for l in lines]  # extract numbers, convert the number strings to ints
        array = np.array(values, dtype=np.int32)
        print(array)