searching a pandas dataframe using PySimpleGUI - pandas

How do I update my list box using pysimple gui as below
so the user input is AP and the list box suggests "APPLE"
the issue as I see it is describing the updated listbox as the user is inputting with respect to the pandas dataframe
import PySimpleGUI as sg
import pandas as pd
sg.theme('Default1')
pd.set_option('display.max_rows',None)
formulation =pd.read_csv('FORMULATIONS.csv')
names=formulation["PRODUCT"]
#names=product.values.tolist()
#names=formulation["PRODUCT"].to_string
#left side search
left_col=[[sg.Text('SEARCH')],
[sg.Input(size=(20,1),enable_events=True,key='-INPUT-',do_not_clear=True)],
[sg.Listbox(names,size=(50,len(names)),key='-LIST-',enable_events=True)]]
#right side batch sheet
right_col=[[sg.Text('Product : \n \n ITEM | RAW MATERIAL |')],
[sg.Text(size=(40,1),key='-TOUT-')]]
#together
layout=[[sg.Column(left_col,element_justification='c'),sg.VSeperator(),sg.Column(right_col)]]
#create window
window =sg.Window('BF-2.1',layout,resizable=True)
#event loop
while True:
event, values =window.Read()
if event in (sg.WIN_CLOSED,'Exit'):
break
if values['-INPUT-'] != '' :
search =values['-INPUT-']
new_values=[formulation["PRODUCT"]==['-INPUT-']] #how to use the input to navigate
window.Element('-LIST-').Update(new_values)
else:
window.Element('-LIST-').Update(names)
if event =='-LIST-' and len(values['-LIST-']):
sg.popup('Selected',values['-LIST-'])
window.close()
have tried
new_values=[x for x in names if search in x]

Use df.loc[df["PRODUCT"]==text]["KIND"] to get items which matched the text.
Following code demo how to get event from Input element to filtered the DataFrame to update the List element. Try to input 'car', 'motorcycleorship` to get the List element updated, or empty the List element to get all.
import pandas as pd
import PySimpleGUI as sg
data = [
["car", item] for item in ('SUV', 'Hatchback', 'Crossover', 'Convertible', 'Sedan', 'Sports Car', 'Coupe', 'Minivan', 'Station Wagon', 'Pichup Truck')] + [
["motorcycle", item] for item in ('standard', 'cruiser', 'touring', 'sports', 'off-road', 'dual-purpose')] + [
["ship", item] for item in ('Container', 'Bulk Carrier', 'Tanker', 'Passenger', 'Naval', 'Offshore', 'Special Purpose')]
df = pd.DataFrame(data, columns=["PRODUCT", "KIND"])
left_col=[
[sg.Text('SEARCH')],
[sg.Input(size=20, enable_events=True, key='-INPUT-')],
[sg.Listbox(df["KIND"], size=(50, 10), key='-LIST-', enable_events=True)],
]
right_col=[
[sg.Text('Product : \n \n ITEM | RAW MATERIAL |')],
[sg.Text(size=40, key='-TOUT-')],
]
layout=[
[sg.Column(left_col,element_justification='c'),
sg.VSeperator(),
sg.Column(right_col)],
]
window = sg.Window('BF-2.1', layout, resizable=True)
while True:
event, values = window.read()
if event == sg.WIN_CLOSED:
break
if event == '-INPUT-':
if values[event]:
text = values['-INPUT-'].lower()
new_values= df.loc[df["PRODUCT"]==text]["KIND"]
window['-LIST-'].update(new_values)
else:
new_values = df["KIND"]
window['-LIST-'].update(new_values)
if event =='-LIST-' and len(values['-LIST-']):
sg.popup('Selected', values['-LIST-'])
window.close()

Related

Update PysimpleGUI window with values from Excel sheet

I am trying to reference a Pandas dataframe in Pysimplegui
`
# function definitions
def retrieve_info():
if values['-UPC-'] == '':
search_box = values['-UPC-']
records = item_info.iloc[item_info[0] == search_box]
for records in records:
window['-SKU-'].update(records[item_info['Item Number']])
window['-DESCRIPTION-'].update(records[item_info['Item Description']])
window['-UOM-'].update(records[item_info['UOM']])
window['-LOCATION-'].update(records[item_info['LOCATION']])
`
trying to get the fields below Scan Product to populate with information but instead get this error. KeyError: 'UPC'
Demo code for you
import pandas as pd
import PySimpleGUI as sg
# table = pd.read_excel('table.xlsx')
data = [[(i+1)*(j+1) for i in range(9)] for j in range(9)]
table = pd.DataFrame(data, columns=[i+1 for i in range(9)])
layout = [
[sg.Text("A (1~9)"), sg.Input(size=5, enable_events=True, key='A')],
[sg.Text("B (1~9)"), sg.Input(size=5, enable_events=True, key='B')],
[sg.Text(f"A x B = ", expand_x=True, key='Result')],
]
window = sg.Window('Title', layout)
while True:
event, values = window.read()
if event == sg.WIN_CLOSED:
break
elif event in 'AB':
a, b = values['A'], values['B']
if a and a in "123456789" and b and b in "123456789":
window['Result'].update(f'{a} x {b} = {table[int(a)][int(b)-1]}')
else:
window['Result'].update('Wrong A or B')
window.close()
There's nothing special for the table.xlsx, it is something like this.

Creating a registry with PySimpleGUI but I can't create the columns with the values ​of the keys

#error creating table with desired column
from PySimpleGUI import PySimpleGUI as sg
import pandas as pd
# Layout
sg.theme('Reddit')
layout = [
[sg.Text('Ticker: '), sg.Input(key='Ticker')],
[sg.Text('Quantidade de Papéis: '), sg.Input(key='Qtd_de_papeis')],
[sg.Text('Valor: '), sg.Input(key='Valor_pago')],
[sg.Text('Data:'), sg.Input(key='Data')],
[sg.Button('Adicionar'), sg.Button('Cancelar')]
]
# Janela
window = sg.Window('Tela de Cadastro', layout)
# Ler os eventos
while True:
events, values = window.read()
if events == (sg.WIN_CLOSED, 'Cancelar'):
break
if events == 'Adicionar':
columns = list(values.keys())
rows = list(values.values())
print(rows)
print(columns)
df.to_csv('registro.csv', sep=';', mode='a', index=False)
df_new = pd.read_csv('registro.csv', sep=';')
window.close()
print(df_new)
#I wanted to know if there is a way to assign columns or will it be necessary to create variables
Not sure if it work for you.
Here, it will create new CSV file when first record added.
You can check if file exist or not.
If exist, you can set headings = False before your event loop.
from PySimpleGUI import PySimpleGUI as sg
import pandas as pd
fields = {
'Ticker' : 'Ticker:',
'Qtd_de_papeis' : 'Quantidade de Papéis:',
'Valor_pago' : 'Valor:',
'Data' : 'Data:'
}
columns = list(fields.keys())
sg.theme('Reddit')
layout = [
[sg.Text(text), sg.Push(), sg.Input(key=key)] for key, text in fields.items()] + [
[sg.Button(button) for button in ('Adicionar', 'Cancelar')]
]
window = sg.Window('Tela de Cadastro', layout)
headings = True
while True:
events, values = window.read()
if events in (sg.WIN_CLOSED, 'Cancelar'):
break
if events == 'Adicionar':
df = pd.DataFrame({column:[] for column in columns})
df.loc[0] = [values[key] for key in columns]
if headings:
df.to_csv('registro.csv', sep=';', index=False)
else:
df.to_csv('registro.csv', sep=';', mode='a', index=False, header=False)
headings = False
df_new = pd.read_csv('registro.csv', sep=';')
print(df_new)
window.close()
Show, serviu muito bem.. Obrigado pela atenção.

How to check & change datatype of a column of panda dataframe using combobox in jupyter notebook?

I would like to convert the data type of a column but using ipython wigets:
Combobox1 will display all columns of the data frame.
Disabled Text1 box will show the existing datatype of the column selected at step 1.
Next Combobox2 will give options like, {'int', 'float', 'datetime', 'object'}
Text2 box will show something like:
df['customerID'].dtypes = String
Output in Text2 must be stored in a variable for future programming.
Button to execute data type conversion.
Code that I referred(but not been able to customize completely):
# Common Imports for Widgets
from ipywidgets import interact, interactive, fixed, interact_manual
import ipywidgets as widgets
df = pd.read_csv('TelcomCustomer-Churn.csv', index_col = 0)
foo = df.columns
# Function to apply to drop box object
def bar(x):
print(x,'\n') # Whole object
print(x.new,'\n') # New value
# creation of a widget dropdown object
box1 = widgets.Dropdown(
options=foo, # Object to iterate over
description='Column Name:',
value=foo[1], # Default value selection
rows=len(foo), # The number of rows to display when showing the box
interactive=True,
);
#text box
text = widgets.Text(
value='last',
placeholder='datatype',
description='String:',
disabled=True
)
def callback(wdgt):
with output:
clear_output
display(wdgt.value)
text.on_submit(callback)
# Drop box of k,v like pairs
box2 = widgets.Dropdown(
options=[('Object', 1), ('float', 2), ('int', 3), ('datetime', 4)],
value=1,
description='datatypes:',
)
# Button to click
select_button = widgets.Button(
description='Convert Datatype',
# missing action to be perfomed
disabled=False
)
# Event Handlers
box1.observe(bar,names='value')
text.observe(bar,names='value')
box2.observe(bar,names='value')
select_button.on_click(get_user_selection)
[enter image description here][1]
ui = widgets.HBox([box1,text,box2,select_button])
# display the UI
display(ui)
Code Output

Webscraping several URLs into panda df

Need some help appending several webscraping resaults to a panda df.
Currently im only getting the output from one of the URLs to the DF.
I left out the URLs, if you need them i will supply them to you.
##libs
import bs4
import requests
import re
from time import sleep
import pandas as pd
from bs4 import BeautifulSoup as bs
##webscraping targets
URLs = ["URL1","URL2","URL3"]
## Get columns
column_list = []
r1 = requests.get(URLs[0])
soup1 = bs(r1.content)
data1 = soup1.find_all('dl', attrs= {"class": "border XSText rightAlignText noMarginTop highlightOnHover thickBorderBottom noTopBorder"})
columns = soup1.find_all('dt')
for col in columns:
column_list.append(col.text.strip()) # strip() removes extra space from the text
##Get values
value_list = []
for url in URLs:
r1 = requests.get(url)
soup1 = bs(r1.content)
data1 = soup1.find_all('dl', attrs= {"class": "border XSText rightAlignText noMarginTop highlightOnHover thickBorderBottom noTopBorder"})
values = soup1.find_all('dd')
for val in values:
value_list.append(val.text.strip())
df=pd.DataFrame(list(zip(column_list,value_list)))
df.transpose()
Current output only showing the resaults of one URL:
Expected output:
The problem here is with your zip function. It will only zip the values until the length of the shortest list, in this case, the column_list. Leaving all the other values unused.
If you want to append the other values to the dataframe as well you will have to iterate over then. So change the last two lines on your code to this and it should work:
result = [[i] for i in column_list]
for i, a in enumerate(value_list):
result[i % len(column_list)].extend([a])
df = pd.DataFrame(result)
df.transpose()

Python 3.6 Pandas Difflib Get_Close_Matches to filter a dataframe with user input

Using a csv imported using a pandas dataframe, I am trying to search one column of the df for entries similar to a user generated input. Never used difflib before and my tries have ended in a TypeError: object of type 'float' has no len() or an empty [] list.
import difflib
import pandas as pd
df = pd.read_csv("Vendorlist.csv", encoding= "ISO-8859-1")
word = input ("Enter a vendor: ")
def find_it(w):
w = w.lower()
return difflib.get_close_matches(w, df.vendorname, n=50, cutoff=.6)
alternatives = find_it(word)
print (alternatives)
The error seems to occur at "return.difflib.get_close_matches(w, df.vendorname, n=50, cutoff=.6)"
Am attempting to get similar results to "word" with a column called 'vendorname'.
Help is greatly appreciated.
Your column vendorname is of the incorrect type.
Try in your return statement:
return difflib.get_close_matches(w, df.vendorname.astype(str), n=50, cutoff=.6)
import difflib
import pandas as pd
df = pd.read_csv("Vendorlist.csv", encoding= "ISO-8859-1")
word = input ("Enter a vendor: ")
def find_it(w):
w = w.lower()
return difflib.get_close_matches(w, df.vendorname.astype(str), n=50, cutoff=.6)
alternatives = find_it(word)
print (alternatives)
As stated in the comments by #johnchase
The question also mentions the return of an empty list. The return of get_close_matches is a list of matches, if no item matched within the cutoff an empty list will be returned – johnchase
I've skipped the:
astype(str)in (return difflib.get_close_matches(w, df.vendorname.astype(str), n=50, cutoff=.6))
Instead used:
dtype='string' in (df = pd.read_csv("Vendorlist.csv", encoding= "ISO-8859-1"))