Spaces:
Runtime error
Runtime error
Upload 3 files
Browse files- app.py +83 -0
- download.py +139 -0
- requirements.txt +3 -0
app.py
ADDED
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import pandas as pd
|
3 |
+
import traceback
|
4 |
+
import sys
|
5 |
+
|
6 |
+
from st_aggrid import AgGrid
|
7 |
+
from st_aggrid.grid_options_builder import GridOptionsBuilder
|
8 |
+
from st_aggrid.shared import JsCode
|
9 |
+
from download import download_button
|
10 |
+
from st_aggrid import GridUpdateMode, DataReturnMode
|
11 |
+
|
12 |
+
# Page config is set once with icon title and display style. Wide mode since we want screen real estate for wide CSV files
|
13 |
+
st.set_page_config(page_icon="📝", page_title="📝CSV Data Analyzer📊", layout="wide")
|
14 |
+
|
15 |
+
# Style
|
16 |
+
def _max_width_():
|
17 |
+
max_width_str = f"max-width: 1800px;"
|
18 |
+
st.markdown(
|
19 |
+
f"""
|
20 |
+
<style>
|
21 |
+
.reportview-container .main .block-container{{
|
22 |
+
{max_width_str}
|
23 |
+
}}
|
24 |
+
</style>
|
25 |
+
""",
|
26 |
+
unsafe_allow_html=True,
|
27 |
+
)
|
28 |
+
|
29 |
+
# Title Bar with Images and Icons
|
30 |
+
col1, col2, col3 = st.columns([1,6,1])
|
31 |
+
with col1:
|
32 |
+
st.image("https://cdnb.artstation.com/p/assets/images/images/054/910/875/large/aaron-wacker-cyberpunk-computer-brain-design.jpg?1665656558",width=624,)
|
33 |
+
with col2:
|
34 |
+
st.title("📝 CSV Data Analyzer 📊")
|
35 |
+
with col3:
|
36 |
+
st.image("https://cdna.artstation.com/p/assets/images/images/054/910/878/large/aaron-wacker-cyberpunk-computer-devices-iot.jpg?1665656564",width=624,)
|
37 |
+
|
38 |
+
# Upload
|
39 |
+
c29, c30, c31 = st.columns([1, 6, 1])
|
40 |
+
with c30:
|
41 |
+
uploaded_file = st.file_uploader("", key="1", help="To activate 'wide mode', go to the menu > Settings > turn on 'wide mode'",)
|
42 |
+
if uploaded_file is not None:
|
43 |
+
file_container = st.expander("Check your uploaded .csv")
|
44 |
+
#try:
|
45 |
+
shows = pd.read_csv(uploaded_file)
|
46 |
+
#except:
|
47 |
+
# print(sys.exc_info()[2])
|
48 |
+
|
49 |
+
uploaded_file.seek(0)
|
50 |
+
file_container.write(shows)
|
51 |
+
else:
|
52 |
+
st.info(f"""⬆️Upload a 📝.CSV file. Examples: [Chatbot](https://huggingface.co/datasets/awacke1/Carddata.csv) [Mindfulness](https://huggingface.co/datasets/awacke1/MindfulStory.csv) [Wikipedia](https://huggingface.co/datasets/awacke1/WikipediaSearch)""")
|
53 |
+
st.stop()
|
54 |
+
|
55 |
+
# DisplayGrid
|
56 |
+
gb = GridOptionsBuilder.from_dataframe(shows)
|
57 |
+
gb.configure_default_column(enablePivot=True, enableValue=True, enableRowGroup=True)
|
58 |
+
gb.configure_selection(selection_mode="multiple", use_checkbox=True)
|
59 |
+
gb.configure_side_bar()
|
60 |
+
gridOptions = gb.build()
|
61 |
+
st.success(f"""💡 Tip! Hold shift key when selecting rows to select multiple rows at once.""")
|
62 |
+
response = AgGrid(
|
63 |
+
shows,
|
64 |
+
gridOptions=gridOptions,
|
65 |
+
enable_enterprise_modules=True,
|
66 |
+
update_mode=GridUpdateMode.MODEL_CHANGED,
|
67 |
+
data_return_mode=DataReturnMode.FILTERED_AND_SORTED,
|
68 |
+
fit_columns_on_grid_load=False,
|
69 |
+
)
|
70 |
+
|
71 |
+
# Filters
|
72 |
+
df = pd.DataFrame(response["selected_rows"])
|
73 |
+
st.subheader("Filtered data will appear below 📊 ")
|
74 |
+
st.text("")
|
75 |
+
st.table(df)
|
76 |
+
st.text("")
|
77 |
+
|
78 |
+
# Download
|
79 |
+
c29, c30, c31 = st.columns([1, 1, 2])
|
80 |
+
with c29:
|
81 |
+
CSVButton = download_button(df,"Dataset.csv","Download CSV file",)
|
82 |
+
with c30:
|
83 |
+
CSVButton = download_button(df,"Dataset.txt","Download TXT file",)
|
download.py
ADDED
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import pickle
|
3 |
+
import pandas as pd
|
4 |
+
import json
|
5 |
+
import base64
|
6 |
+
import uuid
|
7 |
+
import re
|
8 |
+
|
9 |
+
import importlib.util
|
10 |
+
|
11 |
+
|
12 |
+
def import_from_file(module_name: str, filepath: str):
|
13 |
+
"""
|
14 |
+
Imports a module from file.
|
15 |
+
Args:
|
16 |
+
module_name (str): Assigned to the module's __name__ parameter (does not
|
17 |
+
influence how the module is named outside of this function)
|
18 |
+
filepath (str): Path to the .py file
|
19 |
+
Returns:
|
20 |
+
The module
|
21 |
+
"""
|
22 |
+
spec = importlib.util.spec_from_file_location(module_name, filepath)
|
23 |
+
module = importlib.util.module_from_spec(spec)
|
24 |
+
spec.loader.exec_module(module)
|
25 |
+
return module
|
26 |
+
|
27 |
+
|
28 |
+
def notebook_header(text):
|
29 |
+
"""
|
30 |
+
Insert section header into a jinja file, formatted as notebook cell.
|
31 |
+
Leave 2 blank lines before the header.
|
32 |
+
"""
|
33 |
+
return f"""# # {text}
|
34 |
+
"""
|
35 |
+
|
36 |
+
|
37 |
+
def code_header(text):
|
38 |
+
"""
|
39 |
+
Insert section header into a jinja file, formatted as Python comment.
|
40 |
+
Leave 2 blank lines before the header.
|
41 |
+
"""
|
42 |
+
seperator_len = (75 - len(text)) / 2
|
43 |
+
seperator_len_left = math.floor(seperator_len)
|
44 |
+
seperator_len_right = math.ceil(seperator_len)
|
45 |
+
return f"# {'-' * seperator_len_left} {text} {'-' * seperator_len_right}"
|
46 |
+
|
47 |
+
|
48 |
+
def to_notebook(code):
|
49 |
+
"""Converts Python code to Jupyter notebook format."""
|
50 |
+
notebook = jupytext.reads(code, fmt="py")
|
51 |
+
return jupytext.writes(notebook, fmt="ipynb")
|
52 |
+
|
53 |
+
|
54 |
+
def open_link(url, new_tab=True):
|
55 |
+
"""Dirty hack to open a new web page with a streamlit button."""
|
56 |
+
# From: https://discuss.streamlit.io/t/how-to-link-a-button-to-a-webpage/1661/3
|
57 |
+
if new_tab:
|
58 |
+
js = f"window.open('{url}')" # New tab or window
|
59 |
+
else:
|
60 |
+
js = f"window.location.href = '{url}'" # Current tab
|
61 |
+
html = '<img src onerror="{}">'.format(js)
|
62 |
+
div = Div(text=html)
|
63 |
+
st.bokeh_chart(div)
|
64 |
+
|
65 |
+
|
66 |
+
def download_button(object_to_download, download_filename, button_text):
|
67 |
+
"""
|
68 |
+
Generates a link to download the given object_to_download.
|
69 |
+
From: https://discuss.streamlit.io/t/a-download-button-with-custom-css/4220
|
70 |
+
Params:
|
71 |
+
------
|
72 |
+
object_to_download: The object to be downloaded.
|
73 |
+
download_filename (str): filename and extension of file. e.g. mydata.csv,
|
74 |
+
some_txt_output.txt download_link_text (str): Text to display for download
|
75 |
+
link.
|
76 |
+
button_text (str): Text to display on download button (e.g. 'click here to download file')
|
77 |
+
pickle_it (bool): If True, pickle file.
|
78 |
+
Returns:
|
79 |
+
-------
|
80 |
+
(str): the anchor tag to download object_to_download
|
81 |
+
Examples:
|
82 |
+
--------
|
83 |
+
download_link(your_df, 'YOUR_DF.csv', 'Click to download data!')
|
84 |
+
download_link(your_str, 'YOUR_STRING.txt', 'Click to download text!')
|
85 |
+
"""
|
86 |
+
|
87 |
+
# if:
|
88 |
+
if isinstance(object_to_download, bytes):
|
89 |
+
pass
|
90 |
+
|
91 |
+
elif isinstance(object_to_download, pd.DataFrame):
|
92 |
+
object_to_download = object_to_download.to_csv(index=False)
|
93 |
+
# Try JSON encode for everything else
|
94 |
+
else:
|
95 |
+
object_to_download = json.dumps(object_to_download)
|
96 |
+
|
97 |
+
try:
|
98 |
+
# some strings <-> bytes conversions necessary here
|
99 |
+
b64 = base64.b64encode(object_to_download.encode()).decode()
|
100 |
+
except AttributeError as e:
|
101 |
+
b64 = base64.b64encode(object_to_download).decode()
|
102 |
+
|
103 |
+
button_uuid = str(uuid.uuid4()).replace("-", "")
|
104 |
+
button_id = re.sub("\d+", "", button_uuid)
|
105 |
+
|
106 |
+
custom_css = f"""
|
107 |
+
<style>
|
108 |
+
#{button_id} {{
|
109 |
+
display: inline-flex;
|
110 |
+
align-items: center;
|
111 |
+
justify-content: center;
|
112 |
+
background-color: rgb(255, 255, 255);
|
113 |
+
color: rgb(38, 39, 48);
|
114 |
+
padding: .25rem .75rem;
|
115 |
+
position: relative;
|
116 |
+
text-decoration: none;
|
117 |
+
border-radius: 4px;
|
118 |
+
border-width: 1px;
|
119 |
+
border-style: solid;
|
120 |
+
border-color: rgb(230, 234, 241);
|
121 |
+
border-image: initial;
|
122 |
+
}}
|
123 |
+
#{button_id}:hover {{
|
124 |
+
border-color: rgb(246, 51, 102);
|
125 |
+
color: rgb(246, 51, 102);
|
126 |
+
}}
|
127 |
+
#{button_id}:active {{
|
128 |
+
box-shadow: none;
|
129 |
+
background-color: rgb(246, 51, 102);
|
130 |
+
color: white;
|
131 |
+
}}
|
132 |
+
</style> """
|
133 |
+
|
134 |
+
dl_link = (
|
135 |
+
custom_css
|
136 |
+
+ f'<a download="{download_filename}" id="{button_id}" href="data:file/txt;base64,{b64}">{button_text}</a><br><br>'
|
137 |
+
)
|
138 |
+
|
139 |
+
st.markdown(dl_link, unsafe_allow_html=True)
|
requirements.txt
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
streamlit
|
2 |
+
streamlit-aggrid==0.2.2-2
|
3 |
+
click==8
|