Related
I have been working with PySimpleGUI, where I'm trying to change from an initial empty table as presented in the figure 1, there can be observed how the initial table at the bottom is empty and has three columns.
Figure 1:
In here I use a script where you imput your databases, and click on -GENERATE- to apply some statistcs and present it as an image on the rigth side and a table with statistical data on the bottom.
Here you can see the script:
Script (deleted irrelevant things):
# TABLE DATA
data= {
("Count", "-", "-"),
("Average", " -", "-"),
("Median", "-", "-"),
("Min", " -", "-"),
("Max", "-", "-"),
("StdDev", " -", "-"),
("Q1", "-", "-"),
("Q2", " -", "-"),
}
headings = ["STAT", "DATABASE A", "DATABASE B"] #list
# Table generation:
list_variables = ["Count", "Average", "Median", "Min", "Max", "StdDev", "Q1", "Q3"]
dicts = {}
def tablegen (imp_dict): #enter dictionary from -FOLDERS-
for k in imp_dict.items():
del k[1]["survey"]
v = [k[1].shape[0],np.average(k[1].iloc[:,0]) ,np.median(k[1].iloc[:,0]),min(k[1].iloc[:,0]),max(k[1].iloc[:,0]),np.std(k[1].iloc[:,0]),np.quantile(k[1].iloc[:,0],0.25),np.quantile(k[1].iloc[:,0],0.75)]
final[k[0]]=v
# LAYOUT
layout = [
[sg.Button('GENERATE'),sg.Button('REMOVE')],
[sg.Text('Generated table:')],
[sg.Table(values=data, headings=headings, max_col_width=25,
auto_size_columns=True,
display_row_numbers=False,
justification='center',
num_rows=5,
alternating_row_color='lightblue',
key='-TABLE-',
selected_row_colors='red on yellow',
enable_events=True,
expand_x=False,
expand_y=True,
vertical_scroll_only=True,
tooltip='This is a table')]
]
window = sg.Window('Tool', layout)
# ------ Loops ------
while True:
if event == 'GENERATE': #problems
selection(file_list) #some functions blah blah, it generates a csv file called "minimum"
#This is the archive (minimum.csv) that is produced after clicking -GENERATE- to make the desired table (it applies some functions).
file_loc2 = (real_path + "/minimum.csv")
try:
archive = pd.read_csv(file_loc2, sep=",")
df_names = pd.unique(archive["survey"]) #column names
for name in df_names: #enter initial archive
dicts[name] = pd.DataFrame(data= (archive.loc[archive["survey"] == name ]),columns=("Wavelength_(nm)", "survey")) #iteration blah blah
tablegen(dicts) #this generates the statistical values for the table.
final_df = pd.DataFrame(data= final, index=list_variables, columns=df_names)
final_df = final_df.round(decimals=1)
final_lists = final_df.values.tolist()
# I tried using a DataFrame and produced the table in figure 2 (final_df), and a list of list (as recomended at PySimpleGUI webpage) final_lists and produced the table in figure 3.
window["-TABLE-"].update(final_df) #or .update(final_lists)
except Exception as E:
print(f'** Error {E} **')
pass # if something weird happened making the full filename
window.close()
The issue is this:
In the second and third figures present how this script uses the information from the folders (databases) selected in the left square, and generates the image in the left and supposedly would present DataFrame shown below.
GOAL TABLE TO PRESENT:
final_df:
13 MAR 2018 14 FEB 2018 16 FEB 2018 17 FEB 2018
Count 84.0 25.0 31.0 31.0
Average 2201.5 2202.1 2203.1 2202.9
Median 2201.0 2202.0 2204.0 2204.0
Min 2194.0 2197.0 2198.0 2198.0
Max 2208.0 2207.0 2209.0 2209.0
StdDev 4.0 3.0 3.5 3.5
Q1 2198.0 2199.0 2199.5 2199.5
Q3 2205.0 2205.0 2206.0 2206.0
Figure 2: This is using a DataFrame as imput in the loop -GENERATE-.
Figure 3: This is using a list of lists as imput in the loop -GENERATE-.
As it is observed, the "-TABLE-" is not working the way that I intend. If I use a DataFrame it is just selecting the columns names, and if I use a list of list it ignores the index and column names from the intended goal table.
Also, the table is in both cases not generating more columns even there should be 5 including the index. And how can I change the column names from the initially provided ones?
In the PySimpleGUI demos and call references I can not find something to solve this, also I searched in the web and in older StackOverflow posts, but to be honest I do not find a similar case to this.
I'll be really greatful if somebody can help me to find what I am doing wrong!
Btw sorry for my english, Colombian here.
The number of columns increased per records ? Most of time, the number of rows of a Table element increased per records. Maybe you should take ['Date'] + list_variables as the headings of the Table element, and add each holder as one new row of the Table element.
import pandas as pd
import PySimpleGUI as sg
file = r'd:/Qtable.csv'
"""
Date,Count,Average,Median,Min,Max,StdDev,Q1,Q3
13-Mar-18,84,2201.5,2201,2194,2208,4,2198,2205
14-Mar-18,25,2202.1,2202,2197,2207,3,2199,2205
16-Mar-18,31,2203.1,2204,2198,2209,3.5,2199.5,2206
17-Mar-18,31,2202.9,2204,2198,2209,3.5,2199.5,2206
"""
df = pd.read_csv(file, header=None)
values = df.values.tolist()
headings = values[0]
data = values[1:]
layout = [[sg.Table(data, headings=headings, key='-TABLE-')]]
sg.Window('Table', layout).read(close=True)
Here is my current code:
all_teams = np.unique(march['PitcherTeam'])
all_pitchers = np.unique(march['Pitcher'])
all_pitches = np.unique(march['TaggedPitchType'])
_ = widgets.interact(pitch_chart, df=march, team=list(all_teams), pitcher = list(all_pitchers), pitch_type = list(all_pitches))
It currently outputs this:
pitch chart
I want it to be able to eliminate future drop down choices based on choices they have already made. For example, when they select ORE_DUC as their team, I want it to only present pitchers that play for ORE_DUC in the next line, and then based on the pitcher they choose, only present the pitches they pitch.
I'm working on a dynamic scrolling application that somewhat emulates a table format. Unfortunately, due to the speed of the data, the only method that is quick enough to do this is the text widget (Displaying real time stock data in a scrolling table in Python).
Ideally I would like to place a border of every around every "cell" to emulate column and row dividers in a table. However, it seems like similar tags join together if placed next to each other, meaning the border stretches out to the bottom of the text widget.
I have tried using 2 different tag identifiers to trick it into not joining the borders, but it still merges the borders/tags. However, if I change the colour or even the borderwidth to a different value, they no longer join up. Unfortunately, I need a uniform border width.
For a simple example, I have defined 3 tags, 2 have identical properties, and one has a slight difference (colour) to show the effect.
The first two lines use the 2 identical tags for each cell, and the border is fully merged.
The 4th line shows the correct border, but this uses the tag with a different property (colour). The functionality I desire is to have the exact same properties but with a border per cell:
import tkinter as tk
root = tk.Tk()
text = tk.Text(root)
text.pack()
# Define example tags, 2 with identical properties but different identifiers, one with a different property (colour)
text.tag_config("tag1", background="lightgray", borderwidth=1, relief="solid")
text.tag_config("tag2", background="lightgray", borderwidth=1, relief="solid")
text.tag_config("tag3", background="lightyellow", borderwidth=1, relief="solid")
# Insert 4 example lines
text.insert(tk.INSERT, "Line 1 Cell 1 Line 1 Cell 2 Line 1 Cell 3\n")
text.insert(tk.INSERT, "Line 2 Cell 1 Line 2 Cell 2 Line 2 Cell 3\n")
text.insert(tk.INSERT, "\n")
text.insert(tk.INSERT, "Line 4 Cell 1 Line 4 Cell 2 Line 4 Cell 3\n")
# Different tag identities with same properties "join up", so the borders are
text.tag_add("tag1", "1.0", "1.14")
text.tag_add("tag2", "1.14", "1.28")
text.tag_add("tag1", "1.28", "1.42")
# The tags also merge when on a new line, with the line above
text.tag_add("tag1", "2.0", "2.14")
text.tag_add("tag2", "2.14", "2.28")
text.tag_add("tag1", "2.28", "2.42")
# Line 4 has the correct borders, but only because colour for tag3 is different
text.tag_add("tag1", "4.0", "4.14")
text.tag_add("tag3", "4.14", "4.28")
text.tag_add("tag1", "4.28", "4.42")
root.mainloop()
Is there a way around this?
You cannot stop tags from being merged. That is fundamental to how tags work in tkinter.
That being said, there are ways to emulate columns. For example, you can give each column a unique tag ("col1", "col2", etc), and/or give a tag to the characters between each column to create a break between columns.
Note: when you call the insert method you can give pairs of text and tags so that you don't have to add the tags after the fact.
For example, the following function will insert three values at the end of the text widget, adding the tags for each column and column separator. It will insert a blank line if all of the parameters are blank to emulate what your example is doing. This code uses the tags "col0", "col1", "col2", and "sep" rather than your more generic tag names.
def insert_row(col0="", col1="", col2=""):
if col0 == "" and col1 == "" and col2 == "":
text.insert("end", "\n")
else:
text.insert("end",
col0, "col0",
"\t", "sep",
col1, "col1",
"\t", "sep",
col2, "col2",
"\n"
)
Here is an example of its use:
insert_row("Line 1 Cell 1", "Line 1 Cell 2", "Line 1 Cell 3")
insert_row("Line 2 Cell 1", "Line 2 Cell 2", "Line 2 Cell 3")
insert_row()
insert_row("Line 3 Cell 1", "Line 3 Cell 2", "Line 3 Cell 3")
In the following screenshot I changed the color of the middle row to make it stand out:
Can anyone help me figure out how to get my y axis sorted by a field in my dataset?
See code below. I want to sort the y axis which is a string concat field of ADP (a decimal number) and a NFL player name. I want to sort this y axis by the ADP which is a field called "OWNER Player ADP" which i cast as a float once it goes into the pandas dataframe. (I wanted it to be a number with a decimal point)
I also created a field called ADP which is pretty much the same thing but it is a varchar when it enters the pandas dataframe. In either case, I can't seem to get the graph to sort the y axis on either of these two variations of fields... I'm also attaching two screenshots of the current output so you can see the data output and chart output. You can see that Aaron Rodgers is at the top of the list, however he has an ADP of 48.3 . I want the player with the lowest number ADP to be at the top of the list...
import altair as alt
import pandas as pd
from main.views import sql_to_dataframe
#--get draft history for a specifc owner, league, and draft type
query ="""
SELECT draft_type,season,"Player Name","Player Team"
,count(*) "Times Drafted"
,cast(round(cast(SUM(pick_no) AS DECIMAL)/cast(COUNT(DISTINCT draft_id) AS DECIMAL),1) as varchar) "OWNER Player ADP"
,cast(round(cast(SUM(pick_no) AS DECIMAL)/cast(COUNT(DISTINCT draft_id) AS DECIMAL),1) as varchar) "ADP"
,concat(cast(round(cast(SUM(pick_no) AS DECIMAL)/cast(COUNT(DISTINCT draft_id) AS DECIMAL),1) as varchar),' ',"Player Team") "Player ADP"
,1 "x_axis"
FROM
mytable
GROUP BY draft_type,season,draft_type,"Player Name","Player Team"
"""
source = sql_to_dataframe(query)
source['OWNER Player ADP'] = source['OWNER Player ADP'].astype(float)
print(source.head())
base=alt.Chart(
source,
title="Player Average Draft Position"
).encode(
x=alt.X('x_axis:O')
,y=alt.Y('Player ADP:O',sort=alt.EncodingSortField(field="OWNER Player ADP:O",order ='descending', op='min'))
#,tooltip=['Player Team','OWNER Player ADP:O']
)
bar=base.mark_square(size=300).encode(
color=alt.Color('Times Drafted:Q', scale=alt.Scale(scheme="darkred"))#,domain=[5,0])
,tooltip=['Player Team','OWNER Player ADP:O','Times Drafted:N']
)
# Configure text
text = base.mark_text(baseline='middle',color='white').encode(
text='Times Drafted:O'
,tooltip=['Player Team','OWNER Player ADP:O','Times Drafted:N']
)
(bar+text).properties(width=50)#.interactive()
alt.EncodingSortField does not require type codes, and does not parse them out of the input. Instead of
alt.EncodingSortField(field="OWNER Player ADP:O", ...)
use
alt.EncodingSortField(field="OWNER Player ADP", ...)
Trying to get hv graph with ability to tap edges separately from nodes. In my case - all meaningful data bound to edges.
gNodes = hv.Nodes((nodes_data.x,nodes_data.y, nodes_data.nid, nodes_data.name),\
vdims=['name'])
gGraph = hv.Graph(((edges_data.source, edges_data.target, edges_data.name),gNodes),vdims=['name'])
opts = dict(width=1200,height=800,xaxis=None,yaxis=None,bgcolor='black',show_grid=True)
gEdges = gGraph.edgepaths
tiles = gv.tile_sources.Wikipedia()
(tiles * gGraph.edgepaths * gGraph.nodes.opts(size=12)).opts(**opts)
If I use gGraph.edgepaths * gGraph.nodes - where is no edge information displayed with Hover tool.
Inspection policy 'edges' for hv.Graph is not suitable for my task, because no single edge selection available.
Where did edge label information in edgepaths property gone? How to add it?
Thank you!
I've created separate dataframe for each link, then i grouped it by unique link label, and insert empty row between each group (two rows for edge - source and target), like in this case: Pandas: Inserting an empty row after every 2nd row in a data frame
emty_row = pd.Series(np.NaN,edges_data.columns)
insert_f = lambda d: d.append(emty_row, ignore_index=True)
edges_df = edges_test.groupby(by='name', group_keys=False).apply(insert_f).reset_index(drop=True)
and create hv.EdgesPaths from df:
gPaths2= hv.EdgePaths(edges_df, kdims=['lon_conv_a','lat_conv_a'])
TAP and HOVER works fine for me.