Repository: e2nIEE/pandapower

Issue:
plotly draws many labels in the legend for lines and transformers
for lines and transformers, a label is added for each element rather than for all similar elements:

![grafik](https://user-images.githubusercontent.com/28706693/154939625-081708b3-b639-4e7e-ad24-14a074ea8a44.png)


Also, I think edge_center are not necessary in the legend.


Discussion:

Resolving patch:
diff --git a/pandapower/plotting/plotly/simple_plotly.py b/pandapower/plotting/plotly/simple_plotly.py
--- a/pandapower/plotting/plotly/simple_plotly.py
+++ b/pandapower/plotting/plotly/simple_plotly.py
@@ -74,7 +74,8 @@ def get_hoverinfo(net, element, precision=3, sub_index=None):
 def simple_plotly(net, respect_switches=True, use_line_geodata=None, on_map=False,
                   projection=None, map_style='basic', figsize=1, aspectratio='auto', line_width=1,
                   bus_size=10, ext_grid_size=20.0, bus_color="blue", line_color='grey',
-                  trafo_color='green',trafo3w_color='green', ext_grid_color="yellow", filename='temp-plot.html', auto_open=True):
+                  trafo_color='green',trafo3w_color='green', ext_grid_color="yellow",
+                  filename='temp-plot.html', auto_open=True, showlegend=True):
     """
     Plots a pandapower network as simple as possible in plotly.
     If no geodata is available, artificial geodata is generated. For advanced plotting see the tutorial
@@ -129,6 +130,8 @@ def simple_plotly(net, respect_switches=True, use_line_geodata=None, on_map=Fals
 
         **auto_open** (bool, True) - automatically open plot in browser
 
+        **showlegend** (bool, True) - If True, a legend will be shown
+
     OUTPUT:
         **figure** (graph_objs._figure.Figure) figure object
     """
@@ -137,19 +140,40 @@ def simple_plotly(net, respect_switches=True, use_line_geodata=None, on_map=Fals
     trans_element = "trafo"
     trans3w_element = "trafo3w"
     separator_element = "switch"
-    return _simple_plotly_generic(net, respect_switches, use_line_geodata, on_map, projection,
-                                  map_style, figsize, aspectratio, line_width, bus_size,
-                                  ext_grid_size, bus_color, line_color, trafo_color,trafo3w_color, ext_grid_color,
-                                  node_element, branch_element, trans_element, trans3w_element, separator_element,
-                                  create_line_trace, create_bus_trace, get_hoverinfo, filename,
-                                  auto_open=auto_open)
+    return _simple_plotly_generic(net=net,
+                                  respect_separators=respect_switches,
+                                  use_branch_geodata=use_line_geodata,
+                                  on_map=on_map,
+                                  projection=projection,
+                                  map_style=map_style,
+                                  figsize=figsize,
+                                  aspectratio=aspectratio,
+                                  branch_width=line_width,
+                                  node_size=bus_size,
+                                  ext_grid_size=ext_grid_size,
+                                  node_color=bus_color,
+                                  branch_color=line_color,
+                                  trafo_color=trafo_color,
+                                  trafo3w_color=trafo3w_color,
+                                  ext_grid_color=ext_grid_color,
+                                  node_element=node_element,
+                                  branch_element=branch_element,
+                                  trans_element=trans_element,
+                                  trans3w_element=trans3w_element,
+                                  separator_element=separator_element,
+                                  branch_trace_func=create_line_trace,
+                                  node_trace_func=create_bus_trace,
+                                  hoverinfo_func=get_hoverinfo,
+                                  auto_open=auto_open,
+                                  showlegend=showlegend)
 
 
 def _simple_plotly_generic(net, respect_separators, use_branch_geodata, on_map, projection, map_style,
                            figsize, aspectratio, branch_width, node_size, ext_grid_size, node_color,
                            branch_color, trafo_color,trafo3w_color, ext_grid_color, node_element, branch_element,
                            trans_element, trans3w_element, separator_element, branch_trace_func, node_trace_func,
-                           hoverinfo_func, filename='temp-plot.html', auto_open=True):
+                           hoverinfo_func, filename='temp-plot.html', auto_open=True,
+                           showlegend=True):
     version_check()
     # create geocoord if none are available
     branch_geodata = branch_element + "_geodata"
@@ -198,17 +222,17 @@ def _simple_plotly_generic(net, respect_separators, use_branch_geodata, on_map,
     # ----- 3W Trafos ------
     if 'trafo3w' in net:
         hoverinfo = hoverinfo_func(net, element=trans3w_element)
-        trans_trace += create_trafo_trace(net, color=trafo3w_color, trafotype='3W', width=branch_width * 5, trace_name='3w_trafos',
-                                         infofunc=hoverinfo,
-                                         use_line_geodata=use_branch_geodata)
+        trans_trace += create_trafo_trace(net, color=trafo3w_color, trafotype='3W', width=branch_width * 5,
+                                          trace_name='3W transformers', infofunc=hoverinfo,
+                                          use_line_geodata=use_branch_geodata)
     # ----- Ext grid ------
     # get external grid from _create_node_trace
     marker_type = 'circle' if on_map else 'square'  # workaround because doesn't appear on mapbox if square
     hoverinfo = hoverinfo_func(net, element="ext_grid")
     ext_grid_trace = _create_node_trace(net, nodes=net.ext_grid[node_element], size=ext_grid_size,
                                         patch_type=marker_type, color=ext_grid_color,
-                                        infofunc=hoverinfo, trace_name='external_grid',
+                                        infofunc=hoverinfo, trace_name='external grid',
                                         node_element=node_element, branch_element=branch_element)
     return draw_traces(branch_traces + trans_trace + ext_grid_trace + node_trace,
-                       aspectratio=aspectratio, figsize=figsize, on_map=on_map,
-                       map_style=map_style, filename=filename, auto_open=auto_open)
+                       showlegend=showlegend, aspectratio=aspectratio, figsize=figsize,
+                       on_map=on_map, map_style=map_style, filename=filename, auto_open=auto_open)
diff --git a/pandapower/plotting/plotly/traces.py b/pandapower/plotting/plotly/traces.py
--- a/pandapower/plotting/plotly/traces.py
+++ b/pandapower/plotting/plotly/traces.py
@@ -77,7 +77,8 @@ def get_line_neutral(coord):
 
 
 def create_edge_center_trace(line_trace, size=1, patch_type="circle", color="white", infofunc=None,
-                             trace_name='edge_center', use_line_geodata=False):
+                             trace_name='edge_center', use_line_geodata=False, showlegend=False,
+                             legendgroup=None):
     """
     Creates a plotly trace of pandapower buses.
 
@@ -106,7 +107,8 @@ def create_edge_center_trace(line_trace, size=1, patch_type="circle", color="whi
     # color = get_plotly_color(color)
 
     center_trace = dict(type='scatter', text=[], mode='markers', hoverinfo='text', name=trace_name,
-                        marker=dict(color=color, size=size, symbol=patch_type))
+                        marker=dict(color=color, size=size, symbol=patch_type),
+                        showlegend=showlegend, legendgroup=legendgroup)
 
     if not use_line_geodata:
         center_trace['x'], center_trace['y'] = (line_trace[0]["x"][1::4], line_trace[0]["y"][1::4])
@@ -175,9 +177,23 @@ def create_bus_trace(net, buses=None, size=5, patch_type="circle", color="blue",
     """
     node_element = 'bus'
     branch_element = 'line'
-    return _create_node_trace(net, buses, size, patch_type, color, infofunc, trace_name,
-                              legendgroup, cmap, cmap_vals, cbar_title, cmin, cmax, cpos,
-                              colormap_column, node_element, branch_element)
+    return _create_node_trace(net,
+                              nodes=buses,
+                              size=size,
+                              patch_type=patch_type,
+                              color=color,
+                              infofunc=infofunc,
+                              trace_name=trace_name,
+                              legendgroup=legendgroup,
+                              cmap=cmap,
+                              cmap_vals=cmap_vals,
+                              cbar_title=cbar_title,
+                              cmin=cmin,
+                              cmax=cmax,
+                              cpos=cpos,
+                              colormap_column=colormap_column,
+                              node_element=node_element,
+                              branch_element=branch_element)
 
 
 def _create_node_trace(net, nodes=None, size=5, patch_type='circle', color='blue', infofunc=None,
@@ -334,9 +350,9 @@ def _get_branch_geodata_plotly(net, branches, use_branch_geodata, branch_element
 
 
 def create_line_trace(net, lines=None, use_line_geodata=True, respect_switches=False, width=1.0,
-                      color='grey', infofunc=None, trace_name='lines', legendgroup=None,
+                      color='grey', infofunc=None, trace_name='lines', legendgroup='lines',
                       cmap=None, cbar_title=None, show_colorbar=True, cmap_vals=None, cmin=None,
-                      cmax=None, cpos=1.1):
+                      cmax=None, cpos=1.1, cmap_vals_category='loading_percent'):
     """
     Creates a plotly trace of pandapower lines. It is a power net specific wrapper function for the
     more generic _create_line_trace function.
@@ -383,10 +399,26 @@ def create_line_trace(net, lines=None, use_line_geodata=True, respect_switches=F
     node_element = "bus"
     separator_element = "switch"
 
-    return _create_branch_trace(net, lines, use_line_geodata, respect_switches, width, color,
-                                infofunc, trace_name, legendgroup, cmap, cbar_title, show_colorbar,
-                                cmap_vals, cmin, cmax, cpos, branch_element, separator_element,
-                                node_element)
+    return _create_branch_trace(net=net,
+                                branches=lines,
+                                use_branch_geodata=use_line_geodata,
+                                respect_separators=respect_switches,
+                                width=width,
+                                color=color,
+                                infofunc=infofunc,
+                                trace_name=trace_name,
+                                legendgroup=legendgroup,
+                                cmap=cmap,
+                                cbar_title=cbar_title,
+                                show_colorbar=show_colorbar,
+                                cmap_vals=cmap_vals,
+                                cmin=cmin,
+                                cmax=cmax,
+                                cpos=cpos,
+                                branch_element=branch_element,
+                                separator_element=separator_element,
+                                node_element=node_element,
+                                cmap_vals_category=cmap_vals_category)
 
 
 def _create_branch_trace(net, branches=None, use_branch_geodata=True, respect_separators=False,
@@ -535,7 +567,8 @@ def _create_branch_trace(net, branches=None, use_branch_geodata=True, respect_se
                     branch_element, idx, branch['name']))
 
         line_trace = dict(type='scatter', text=[], hoverinfo='text', mode='lines', name=trace_name,
-                          line=Line(width=width, color=color))
+                          line=Line(width=width, color=color), showlegend=False,
+                          legendgroup=legendgroup)
 
         line_trace['x'], line_trace['y'] = _get_branch_geodata_plotly(net,
                                                                       branches_to_plot.loc[idx:idx],
@@ -547,6 +580,10 @@ def _create_branch_trace(net, branches=None, use_branch_geodata=True, respect_se
         line_trace['text'] = line_info
 
         branch_traces.append(line_trace)
+
+    # enable legend for one element to make the legend group show up in the legend:
+    branch_traces[0]["showlegend"] = True
+
     if show_colorbar and cmap is not None:
 
         cmin = cmap_vals.min() if cmin is None else cmin
@@ -575,12 +612,14 @@ def _create_branch_trace(net, branches=None, use_branch_geodata=True, respect_se
         except:
             pass
     if len(no_go_branches) > 0:
+        ng_traces = []
         no_go_branches_to_plot = net[branch_element].loc[list(no_go_branches)]
         for idx, branch in no_go_branches_to_plot.iterrows():
             line_color = color
             line_trace = dict(type='scatter',
                               text=[], hoverinfo='text', mode='lines', name='disconnected branches',
-                              line=Line(width=width / 2, color='grey', dash='dot'))
+                              line=Line(width=width / 2, color='grey', dash='dot'),
+                              legendgroup="disconnected " + legendgroup, showlegend=False)
 
             line_trace['x'], line_trace['y'] = _get_branch_geodata_plotly(net,
                                                                           no_go_branches_to_plot.loc[
@@ -594,10 +633,11 @@ def _create_branch_trace(net, branches=None, use_branch_geodata=True, respect_se
             except (KeyError, IndexError, AttributeError):
                 line_trace["text"] = branch['name']
 
-            branch_traces.append(line_trace)
+            ng_traces.append(line_trace)
+        # enable legend for one element to make the legend group show up in the legend:
+        ng_traces[0]["showlegend"] = True
+        branch_traces += ng_traces
 
-            if legendgroup:
-                line_trace['legendgroup'] = legendgroup
     # sort infofunc so that it is the correct order lines_to_plot + no_go_lines_to_plot
     if infofunc is not None:
         if not isinstance(infofunc, pd.Series) and isinstance(infofunc, Iterable) and \
@@ -611,13 +651,15 @@ def _create_branch_trace(net, branches=None, use_branch_geodata=True, respect_se
             sorted_idx += no_go_branches_to_plot.index.tolist()
         infofunc = infofunc.loc[sorted_idx]
     center_trace = create_edge_center_trace(branch_traces, color=color, infofunc=infofunc,
-                                            use_line_geodata=use_branch_geodata)
+                                            use_line_geodata=use_branch_geodata,
+                                            showlegend=False, legendgroup=legendgroup)
     branch_traces.append(center_trace)
+
     return branch_traces
 
 
 def create_trafo_trace(net, trafos=None, color='green', trafotype='2W', width=5, infofunc=None, cmap=None,
-                       trace_name='trafos', cmin=None, cmax=None, cmap_vals=None, matching_params=None,
+                       trace_name='2W transformers', cmin=None, cmax=None, cmap_vals=None, matching_params=None,
                        use_line_geodata=None):
 
     """
@@ -715,7 +757,8 @@ def create_trafo_trace(net, trafos=None, color='green', trafotype='2W', width=5,
         for from_bus1, to_bus1 in connections:
 
             trafo_trace = dict(type='scatter', text=[], line=Line(width=width, color=color),
-                                 hoverinfo='text', mode='lines', name=trace_name)
+                                 hoverinfo='text', mode='lines', name=trace_name,
+                               legendgroup="transformer", showlegend=False)
 
             trafo_trace['text'] = trafo['name'] if infofunc is None else infofunc.loc[idx]
 
@@ -725,9 +768,11 @@ def create_trafo_trace(net, trafos=None, color='green', trafotype='2W', width=5,
                 trafo_trace[k] = [from_bus, (from_bus + to_bus) / 2, to_bus]
 
             trafo_traces.append(trafo_trace)
+    trafo_traces[0]["showlegend"] = True
 
     center_trace = create_edge_center_trace(trafo_traces, color=color, infofunc=infofunc,
-                                                    use_line_geodata=use_line_geodata)
+                                                    use_line_geodata=use_line_geodata,
+                                            showlegend=False, legendgroup="transformer")
     trafo_traces.append(center_trace)
     return trafo_traces
 


Test patch: