tkinter create undetermined number of checkboxes/IntVar - python-3.x

For a project I am working on, I am loading some csv datafile into a dataframe using read_csv. I then print the dataframe on a tkinter frame using some Entry widgets. The user can populate or edit some entries. I would like to create at the beginning of each row a checkbox so that once the user is happy with the edits I upload the "dataframe" for which checkboxes are checked into a database.
When loading the content of the dataframe I can create the desired checkboxes but unfortunately the number of rows of the input datafile is not fixed. For each checkbox I would like to have a unique variable and hence I would like to create an undetermined number of IntVar variables.
within my Tk-inherited class I have the fileLoad function
def fileLoad(self):
df = pd.read_csv(self.filename)
rows, cols = df.shape
for r in range(rows):
for c in range(cols):
e = Entry(self.ViewFrame)
e.insert(0, df.iloc[r, c])
e.grid(row=r, column=c + 1)
so how can I create a variable number of checkboxes positioned in column=0 please?

Ok I find a way as follow:
def fileLoad(self):
df = pd.read_csv(self.filename)
rows, cols = df.shape
vars = []
for r in range(rows):
var = IntVar()
vars.append(var)
ckbox = ttk.Checkbutton(self.ViewFrame, variable=var)
ckbox.grid(row=r+10, column=0)
for c in range(cols):
e = Entry(self.ViewFrame)
e.insert(0, df.iloc[r, c])
e.grid(row=r + 10, column=c + 1)
I store the variables var into a list called vars.

Related

How can I create a variable with data readed with tkinter? Tkinter openfile and create variables of the data

from tkinter.filedialog import askopenfile
root = Tk()
root.geometry('200x100')
def open_file():
file = askopenfile(mode ='r', filetypes =[('Measurement Files', '*.dat')])
if file is not None:
content = file.read()
print(content)
btn = Button(root, text ='Open', command = lambda:open_file())
btn.pack(side = TOP, pady = 10)
mainloop()
Python version 3.7
The code is returning me the content of the file, but how can I do to save each column of the data into different variables?
The data file structure is shown in the pic:
enter image description here
And I want to create 5 list with the data of each column.
Here is a solution where the datafile is parsed into a list of five lists, where each inner list contains one column of data:
content = file.read()
cols = [[], [], [], [], []]
for line in content.split('\n'): # loop over all data lines
for n, col in enumerate(line.split()) # split each line into five columns and loop over
cols[n].append(float(col)) # convert each data to float and append to corresponding column
EDIT (after your comment):
If you really need 5 different variables to store your 5 columns, you may simply add the following line after my previous code:
a, b, c, d, e = cols

Transform JSON to excel table

I have data in csv - 2 columns, 1st column contains member id and second contains characteristics in Key-Value pairs (nested one under another).
I have seen online codes which convert a simple Key-value pairs but not able to transform data like what i have shown above
I want to transform this data into a excel table as below
I did it with this XlsxWriter package, so first you have to install it by running pip install XlsxWriter command.
import csv # to read csv file
import xlsxwriter # to write xlxs file
import ast
# you can change this names according to your local ones
csv_file = 'data.csv'
xlsx_file = 'data.xlsx'
# read the csv file and get all the JSON values into data list
data = []
with open(csv_file, 'r') as csvFile:
# read line by line in csv file
reader = csv.reader(csvFile)
# convert every line into list and select the JSON values
for row in list(reader)[1:]:
# csv are comma separated, so combine all the necessary
# part of the json with comma
json_to_str = ','.join(row[1:])
# convert it to python dictionary
str_to_dict = ast.literal_eval(json_to_str)
# append those completed JSON into the data list
data.append(str_to_dict)
# define the excel file
workbook = xlsxwriter.Workbook(xlsx_file)
# create a sheet for our work
worksheet = workbook.add_worksheet()
# cell format for merge fields with bold and align center
# letters and design border
merge_format = workbook.add_format({
'bold': 1,
'border': 1,
'align': 'center',
'valign': 'vcenter'})
# other cell format to design the border
cell_format = workbook.add_format({
'border': 1,
})
# create the header section dynamically
first_col = 0
last_col = 0
for index, value in enumerate(data[0].items()):
if isinstance(value[1], dict):
# this if mean the JSON key has something else
# other than the single value like dict or list
last_col += len(value[1].keys())
worksheet.merge_range(first_row=0,
first_col=first_col,
last_row=0,
last_col=last_col,
data=value[0],
cell_format=merge_format)
for k, v in value[1].items():
# this is for go in deep the value if exist
worksheet.write(1, first_col, k, merge_format)
first_col += 1
first_col = last_col + 1
else:
# 'age' has only one value, so this else section
# is for create normal headers like 'age'
worksheet.write(1, first_col, value[0], merge_format)
first_col += 1
# now we know how many columns exist in the
# excel, and set the width to 20
worksheet.set_column(first_col=0, last_col=last_col, width=20)
# filling values to excel file
for index, value in enumerate(data):
last_col = 0
for k, v in value.items():
if isinstance(v, dict):
# this is for handle values with dictionary
for k1, v1 in v.items():
if isinstance(v1, list):
# this will capture last 'type' list (['Grass', 'Hardball'])
# in the 'conditions'
worksheet.write(index + 2, last_col, ', '.join(v1), cell_format)
else:
# just filling other values other than list
worksheet.write(index + 2, last_col, v1, cell_format)
last_col += 1
else:
# this is handle single value other than dict or list
worksheet.write(index + 2, last_col, v, cell_format)
last_col += 1
# finally close to create the excel file
workbook.close()
I commented out most of the line to get better understand and reduce the complexity because you are very new to Python. If you didn't get any point let me know, I'll explain as much as I can. Additionally I used enumerate() python Built-in Function. Check this small example which I directly get it from original documentation. This enumerate() is useful when numbering items in the list.
Return an enumerate object. iterable must be a sequence, an iterator, or some other object which supports iteration. The __next__() method of the iterator returned by enumerate() returns a tuple containing a count (from start which defaults to 0) and the values obtained from iterating over iterable.
>>> seasons = ['Spring', 'Summer', 'Fall', 'Winter']
>>> list(enumerate(seasons))
[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
>>> list(enumerate(seasons, start=1))
[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]
Here is my csv file,
and here is the final output of the excel file. I just merged the duplicate header values (matchruns and conditions).

tkinter.insert to print values in next column

I am having a dataframe with 6 columns, what i need from tkinter is to print data in next column everytime when first loop iterate. For eg:
xls = pd.read_excel(file)
df = pd.DataFrame(xls)
df_col = df.columns.values
tree["columns"]=(df_col)
counter = len(df)
for x in range(len(df_col)):
tree.column(x, width=100 )
tree.heading(x, text=df_col[x])
for i in range(counter):
tree.insert("" , 0, values=(df[df_col[x]][i]))
Desired Output:
What im getting from my above code is:
Any help would be appreciated. Thanks in advance.

Python3 - using pandas to group rows, where two colums contain values in forward or reverse order: v1,v2 or v2,v1

I'm fairly new to python and pandas, but I've written code that reads an excel workbook, and groups rows based on the values contained in two columns.
So where Col_1=A and Col_2=B, or Col_1=B and Col_2=A, both would be assigned a GroupID=1.
sample spreadsheet data, with rows color coded for ease of visibility
I've manged to get this working, but I wanted to know if there's a more simpler/efficient/cleaner/less-clunky way to do this.
import pandas as pd
df = pd.read_excel('test.xlsx')
# get column values into a list
col_group = df.groupby(['Header_2','Header_3'])
original_list = list(col_group.groups)
# parse list to remove 'reverse-duplicates'
new_list = []
for a,b in original_list:
if (b,a) not in new_list:
new_list.append((a,b))
# iterate through each row in the DataFrame
# check to see if values in the new_list[] exist, in forward or reverse
for index, row in df.iterrows():
for a,b in new_list:
# if the values exist in forward direction
if (a in df.loc[index, "Header_2"]) and (b in df.loc[index,"Header_3"]):
# GroupID value given, where value is index in the new_list[]
df.loc[index,"GroupID"] = new_list.index((a,b))+1
# else check if value exists in the reverse direction
if (b in df.loc[index, "Header_2"]) and (a in df.loc[index,"Header_3"]):
df.loc[index,"GroupID"] = new_list.index((a,b))+1
# Finally write the DataFrame to a new spreadsheet
writer = pd.ExcelWriter('output.xlsx')
df.to_excel(writer, 'Sheet1')
I know of the pandas.groupby([columnA, columnB]) option, but I couldn't figure a way to create groups that contained both (v1, v2) and (v2,v1).
A boolean mask should do the trick:
import pandas as pd
df = pd.read_excel('test.xlsx')
mask = ((df['Header_2'] == 'A') & (df['Header_3'] == 'B') |
(df['Header_2'] == 'B') & (df['Header_3'] == 'A'))
# Label each row in the original DataFrame with
# 1 if it matches the specified criteria, and
# 0 if it does not.
# This column can now be used in groupby operations.
df.loc[:, 'match_flag'] = mask.astype(int)
# Get rows that match the criteria
df[mask]
# Get rows that do not match the criteria
df[~mask]
EDIT: updated answer to address the groupby requirement.
I would do something like this.
import pandas as pd
df = pd.read_excel('test.xlsx')
#make the ordering consistent
df["group1"] = df[["Header_2","Header_3"]].max(axis=1)
df["group2"] = df[["Header_2","Header_3"]].min(axis=1)
#group them together
df = df.sort_values(by=["group1","group2"])
If you need to deal with more than two columns, I can write up a more general way to do this.

how does this code generate a grid?

I am following a series on tutorials on Object oriented programming. The class matrix is defined as following:
class Matrix():
def __init__(self, rows, columns, default_character='#'):
self.rows = rows
self.columns = columns
self.default_character = default_character
self.grid = [[default_character] * columns for _ in range(rows)]
def print_matrix(self):
for row in self.grid:
print(''.join(row))
The problem is that I do not understand completely how the following
line works:
self.grid = [[default_character] * columns for _ in range(rows)]
That is a list comprehension, which is merely a concise way to create lists. The same list could be created with:
self.grid = []
for _ in range(rows):
self.grid.append([default_character] * columns)

Resources