def selectbox(self, label, options, index=0, format_func=str, key=None): """Display a select widget. Parameters ---------- label : str A short label explaining to the user what this select widget is for. options : list, tuple, numpy.ndarray, pandas.Series, or pandas.DataFrame Labels for the select options. This will be cast to str internally by default. For pandas.DataFrame, the first column is selected. index : int The index of the preselected option on first render. format_func : function Function to modify the display of the labels. It receives the option as an argument and its output will be cast to str. key : str An optional string to use as the unique key for the widget. If this is omitted, a key will be generated for the widget based on its content. Multiple widgets of the same type may not share the same key. Returns ------- any The selected option Example ------- >>> option = st.selectbox( ... 'How would you like to be contacted?', ... ('Email', 'Home phone', 'Mobile phone')) >>> >>> st.write('You selected:', option) """ options = ensure_iterable(options) if not isinstance(index, int): raise StreamlitAPIException( "Selectbox Value has invalid type: %s" % type(index).__name__) if len(options) > 0 and not 0 <= index < len(options): raise StreamlitAPIException( "Selectbox index must be between 0 and length of options") selectbox_proto = SelectboxProto() selectbox_proto.label = label selectbox_proto.default = index selectbox_proto.options[:] = [ str(format_func(option)) for option in options ] ui_value = _get_widget_ui_value("selectbox", selectbox_proto, user_key=key) current_value = ui_value if ui_value is not None else index return_value = (options[current_value] if len(options) > 0 and options[current_value] is not None else NoValue) return self.dg._enqueue("selectbox", selectbox_proto, return_value)
def radio(self, label, options, index=0, format_func=str, key=None, help=None): """Display a radio button widget. Parameters ---------- label : str A short label explaining to the user what this radio group is for. options : list, tuple, numpy.ndarray, pandas.Series, or pandas.DataFrame Labels for the radio options. This will be cast to str internally by default. For pandas.DataFrame, the first column is selected. index : int The index of the preselected option on first render. format_func : function Function to modify the display of radio options. It receives the raw option as an argument and should output the label to be shown for that option. This has no impact on the return value of the radio. key : str An optional string to use as the unique key for the widget. If this is omitted, a key will be generated for the widget based on its content. Multiple widgets of the same type may not share the same key. help : str A tooltip that gets displayed next to the radio. Returns ------- any The selected option. Example ------- >>> genre = st.radio( ... "What\'s your favorite movie genre", ... ('Comedy', 'Drama', 'Documentary')) >>> >>> if genre == 'Comedy': ... st.write('You selected comedy.') ... else: ... st.write("You didn\'t select comedy.") """ options = ensure_iterable(options) if not isinstance(index, int): raise StreamlitAPIException("Radio Value has invalid type: %s" % type(index).__name__) if len(options) > 0 and not 0 <= index < len(options): raise StreamlitAPIException( "Radio index must be between 0 and length of options") radio_proto = RadioProto() radio_proto.label = label radio_proto.default = index radio_proto.options[:] = [ str(format_func(option)) for option in options ] radio_proto.form_id = current_form_id(self.dg) if help is not None: radio_proto.help = help ui_value = register_widget("radio", radio_proto, user_key=key) current_value = ui_value if ui_value is not None else index return_value = (options[current_value] if len(options) > 0 and options[current_value] is not None else NoValue) return self.dg._enqueue("radio", radio_proto, return_value)
def multiselect(self, label, options, default=None, format_func=str, key=None): """Display a multiselect widget. The multiselect widget starts as empty. Parameters ---------- label : str A short label explaining to the user what this select widget is for. options : list, tuple, numpy.ndarray, pandas.Series, or pandas.DataFrame Labels for the select options. This will be cast to str internally by default. For pandas.DataFrame, the first column is selected. default: [str] or None List of default values. format_func : function Function to modify the display of selectbox options. It receives the raw option as an argument and should output the label to be shown for that option. This has no impact on the return value of the selectbox. key : str An optional string to use as the unique key for the widget. If this is omitted, a key will be generated for the widget based on its content. Multiple widgets of the same type may not share the same key. Returns ------- [str] A list with the selected options Example ------- >>> options = st.multiselect( ... 'What are your favorite colors', ... ['Green', 'Yellow', 'Red', 'Blue'], ... ['Yellow', 'Red']) >>> >>> st.write('You selected:', options) .. note:: User experience can be degraded for large lists of `options` (100+), as this widget is not designed to handle arbitrary text search efficiently. See this `thread <https://discuss.streamlit.io/t/streamlit-loading-column-data-takes-too-much-time/1791>`_ on the Streamlit community forum for more information and `GitHub issue #1059 <https://github.com/streamlit/streamlit/issues/1059>`_ for updates on the issue. """ options = ensure_iterable(options) # Perform validation checks and return indices base on the default values. def _check_and_convert_to_indices(options, default_values): if default_values is None and None not in options: return None if not isinstance(default_values, list): # This if is done before others because calling if not x (done # right below) when x is of type pd.Series() or np.array() throws a # ValueError exception. if is_type(default_values, "numpy.ndarray") or is_type( default_values, "pandas.core.series.Series" ): default_values = list(default_values) elif not default_values or default_values in options: default_values = [default_values] else: default_values = list(default_values) for value in default_values: if value not in options: raise StreamlitAPIException( "Every Multiselect default value must exist in options" ) return [options.index(value) for value in default_values] indices = _check_and_convert_to_indices(options, default) multiselect_proto = MultiSelectProto() multiselect_proto.label = label default_value = [] if indices is None else indices multiselect_proto.default[:] = default_value multiselect_proto.options[:] = [str(format_func(option)) for option in options] ui_value = register_widget("multiselect", multiselect_proto, user_key=key) current_value = ui_value.data if ui_value is not None else default_value return_value = [options[i] for i in current_value] return self.dg._enqueue("multiselect", multiselect_proto, return_value)
def select_slider( self, label, options=[], value=None, format_func=str, key=None, ): """ Display a slider widget to select items from a list. This also allows you to render a range slider by passing a two-element tuple or list as the `value`. The difference between `st.select_slider` and `st.slider` is that `select_slider` accepts any datatype and takes an iterable set of options, while `slider` only accepts numerical or date/time data and takes a range as input. Parameters ---------- label : str A short label explaining to the user what this slider is for. options : list, tuple, numpy.ndarray, pandas.Series, or pandas.DataFrame Labels for the slider options. All options will be cast to str internally by default. For pandas.DataFrame, the first column is selected. value : a supported type or a tuple/list of supported types or None The value of the slider when it first renders. If a tuple/list of two values is passed here, then a range slider with those lower and upper bounds is rendered. For example, if set to `(1, 10)` the slider will have a selectable range between 1 and 10. Defaults to first option. format_func : function Function to modify the display of the labels from the options. argument. It receives the option as an argument and its output will be cast to str. key : str An optional string to use as the unique key for the widget. If this is omitted, a key will be generated for the widget based on its content. Multiple widgets of the same type may not share the same key. Returns ------- any value or tuple of any value The current value of the slider widget. The return type will match the data type of the value parameter. Examples -------- >>> color = st.select_slider( ... 'Select a color of the rainbow', ... options=['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet']) >>> st.write('My favorite color is', color) And here's an example of a range select slider: >>> start_color, end_color = st.select_slider( ... 'Select a range of color wavelength', ... options=['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'], ... value=('red', 'blue')) >>> st.write('You selected wavelengths between', start_color, 'and', end_color) """ options = ensure_iterable(options) if len(options) == 0: raise StreamlitAPIException( "The `options` argument needs to be non-empty") is_range_value = isinstance(value, (list, tuple)) slider_value = value # Convert element to index of the elements if is_range_value: slider_value = list(map(lambda v: options.index(v), value)) # type: ignore[no-any-return] start, end = slider_value if start > end: slider_value = [end, start] else: # Simplify future logic by always making value a list try: slider_value = [options.index(value)] except ValueError: if value is not None: raise slider_value = [0] slider_proto = SliderProto() slider_proto.label = label slider_proto.format = "%s" slider_proto.default[:] = slider_value slider_proto.min = 0 slider_proto.max = len(options) - 1 slider_proto.step = 1 # default for index changes slider_proto.data_type = SliderProto.INT slider_proto.options[:] = [ str(format_func(option)) for option in options ] ui_value = register_widget("slider", slider_proto, user_key=key) if ui_value: current_value = getattr(ui_value, "data") else: # Widget has not been used; fallback to the original value, current_value = slider_value # The widget always returns floats, so convert to ints before indexing current_value = list(map(lambda x: options[int(x)], current_value)) # type: ignore[no-any-return] # If the original value was a list/tuple, so will be the output (and vice versa) return_value = tuple( current_value) if is_range_value else current_value[0] return self.dg._enqueue("slider", slider_proto, return_value)