File size: 4,538 Bytes
d6661a1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
from collections import Counter
from typing import List
import numpy as np
import streamlit as st # pylint: disable=import-error
import pandas as pd
class Collapsable:
"""
Creates a collapsable text composed of a preamble (clickable section of text)
and epilogue (collapsable text).
"""
def __init__(self, preamble="", epilogue=""):
self.preamble = preamble
self.epilogue = epilogue
self.small_font = 18
self.large_font = 18
self.sections = []
def add_section(self, heading, text):
# Convert text to bullet points if it is a list
if isinstance(text, list):
text = (
"<ul>"
+ "".join(
[
f'<li style="font-size:{self.small_font}px;" align="justify">{x}</li>'
for x in text
]
)
+ "</ul>"
)
# Append section
self.sections.append((heading, text))
def deploy(self):
secs = "".join(
[
(
"<details>"
f"<summary style='font-size:{self.large_font}px;'>{heading}</summary>"
f"<blockquote style='font-size:{self.small_font}px;max-width: 80%;'"
f"align='justify'>{text}</details>"
)
for heading, text in self.sections
]
)
collapsable_sec = f"""
<ol>
{self.preamble}
{secs}
{self.epilogue}
</ol>
"""
st.markdown(collapsable_sec, unsafe_allow_html=True)
def add_filter(
data_frame_list: List[pd.DataFrame],
name: str,
label: str,
options: List[str] = None,
num_cols: int = 1,
last_is_others: bool = True,
):
"""
Creates a filter on the side bar using checkboxes
"""
# Get list of all options and return if no options are available
all_options = set(data_frame_list[-1][label])
if "-" in all_options:
all_options.remove("-")
if len(all_options) == 0:
return data_frame_list
st.markdown(f"#### {name}")
# Create list of options if selectable options are not provided
if options is None:
options_dict = Counter(data_frame_list[-1][label])
sorted_options = sorted(options_dict, key=options_dict.get, reverse=True)
if "-" in sorted_options:
sorted_options.remove("-")
if len(sorted_options) > 8:
options = list(sorted_options[:7]) + ["others"]
last_is_others = True
else:
options = list(sorted_options)
last_is_others = False
cols = st.columns(num_cols)
instantiated_checkbox = []
for idx in range(len(options)):
with cols[idx % num_cols]:
instantiated_checkbox.append(
st.checkbox(options[idx], False, key=f"{label}_{options[idx]}")
)
selected_options = [
options[idx] for idx, checked in enumerate(instantiated_checkbox) if checked
]
# The last checkbox will always correspond to "other"
if instantiated_checkbox[-1] and last_is_others:
selected_options = selected_options[:-1]
other_options = [x for x in all_options if x not in options]
selected_options = set(selected_options + other_options)
if len(selected_options) > 0:
for idx, _ in enumerate(data_frame_list):
data_frame_list[idx] = data_frame_list[idx][
[
any([x == model_entry for x in selected_options])
for model_entry in data_frame_list[idx][label]
]
]
return data_frame_list
def slider_filter(
data_frame_list: List[pd.DataFrame],
title: str,
filter_by: str,
max_val: int = 1000,
):
"""
Creates slider to filter dataframes according to a given label.
label must be numeric. Values are in millions.
"""
start_val, end_val = st.select_slider(
title,
options=[str(x) for x in np.arange(0, max_val + 1, 10, dtype=int)],
value=("0", str(max_val)),
)
for idx in range(len(data_frame_list)):
data_frame_list[idx] = data_frame_list[idx][
[
int(model_entry) >= int(start_val) * 1000000
and int(model_entry) <= int(end_val) * 1000000
for model_entry in data_frame_list[idx][filter_by]
]
]
return data_frame_list
|