New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sync modifications in GUI to iPython & record history #20
Comments
@pandichef Thanks for the feedback.
Just want to make sure I understand this part. I think it would not be explicitly adding or sending anything new to the shell, right? I'd just have it so any modifications to a DataFrame in the GUI would be done in-place, and the DataFrame object you're seeing in the GUI would be the same one you have in iPython so all in-place modifications would be seen in both, let me know if you had something else in mind. Here are some other thoughts
|
It would be. The idea is that you can edit cells/columns/rows in the GUI and those commands would be "recorded" in iPython. So if you type As for By the way, you might want to check out the Stata or SAS applications. The Stata editor is amazing, but unfortunately only support Stata's native DataFrame object. Stata data editor example... notice how all the commands are "recorded" in the upper left corner. |
Okay I see what you mean, I think these are two separate features
Seems like modifying iPython %history programmatically is not possible and would be a bit of a hack anyways since the user is not actually running that code directly, so I would go with keeping a separate history of commands executed by the GUI. I'm not sure the best way to approach this... Simplest thing would be having a plain string of Python code corresponding to each possible action in the GUI and adding it to a command history (with string substitution to denote the DataFrame names it was applied to). If anyone has a code example of other projects implementing something like to this, please share a link.
That's incorrect. The 1st way is assigning a new object to your import pandas as pd
df = pd.DataFrame({'a':[1,2,None], 'b':[4,5,None]})
print(id(df))
gui_df = df
df.dropna(inplace=True)
print(id(df))
print(gui_df)
import pandas as pd
df = pd.DataFrame({'a':[1,2,None], 'b':[4,5,None]})
print(id(df))
gui_df = df
df = df.dropna()
print(id(df))
print(gui_df)
I've used JMP which is similar (I've been working on adding graphing similar to JMP's Graph Builder), I'll check out Stata too - thanks for the link. |
Ah. I stand corrected about Indeed, I think the first step is to write a utility that maps GUI clicks to python code (as a string). I can try to help with that, but I don't know enough about your implementation of the GUI. |
Yeah I've been meaning to add some documentation on how things are structured. But first I want to do some planned refactoring to clean the code up before trying to get more popularity & requesting contributors. A quick rundown of how it is right now:
That sounds good, I still want to do some thinking about this. One thing that would be useful is a list of all current and future potential actions a person might do in the GUI that affects a DataFrame so I can make sure they'd work in my design. If you have any other ideas, add them to the list Current
Future
|
This looks good. You might also want to include a "how to contribute" section in README.md. I wouldn't prioritize these tbh:
|
UPDATE Record history Sync modifications The code base is also cleaner than last time and since all DataFrame modification happens in that one class it should be easier to follow what's going on. |
A quick note about the recorded history of operations on a data frame in the GUI. How are you applying the filter queries to a dataframe. Through parsing them into pandas operations? You could use the same mechanism to reapply the filters given the filter queries in your top left section. This will make operations performed in the gui reproducible using pandas gui own filtering routine. You can save the operation history string (list of strings) as an attribute in the gui class and should be straight forward to update every time a filter is added or cell is edited. Then reapply the filters will become something like from pandasgui import apply_filters
...
h = gui.history
h
['60<hp<70','Name == Abra']
df_processed = apply_filters(h, df) |
The part that actually applies the filters is just a loop with @track_history
def add_filter(self, expr: str, enabled=True):
filt = Filter(expr=expr, enabled=enabled, failed=False)
self.filters.append(filt)
self.apply_filters()
@track_history
def remove_filter(self, index: int):
self.filters.pop(index)
self.apply_filters()
@track_history
def edit_filter(self, index: int, expr: str):
filt = self.filters[index]
filt.expr = expr
filt.failed = False
self.apply_filters()
@track_history
def toggle_filter(self, index: int):
self.filters[index].enabled = not self.filters[index].enabled
self.apply_filters()
def apply_filters(self):
df = self.dataframe_original
for ix, filt in enumerate(self.filters):
if filt.enabled and not filt.failed:
try:
df = df.query(filt.expr)
except Exception as e:
self.filters[ix].failed = True
logger.exception(e)
self.dataframe = df
self.update() And those
So I'm already storing a history of these methods and arguments, it's just going beyond this and being able to generate runnable code is where things get tricky, since these methods often reference |
Does not have to bu runnable code. Can be a just a function or method as long as it allows to convenietnly reproduce the processed data frame. If you are open to commits I could look into creating a convenient way to reapply to filters from history. |
I noticed that you're looking for feedback... and I think this project is on to something...
My dream DataFrame viewer would work like this:
Now when you change a cell value in the GUI, the application "pushes" the code to the python/ipython shell i.e., you see
df1.at['row', 'col'] = 10
in the shell.Moreover, if you type
df1.at['row', 'col'] = 20
in the shell, the value automatically changes in the GUI. I think such an application would be 1000+ Github stars in no time.The text was updated successfully, but these errors were encountered: