nodes: 0, module; 1, function_definition; 2, function_name:offline_plotly_scatter_bubble; 3, parameters; 4, block; 5, identifier:df; 6, default_parameter; 7, default_parameter; 8, default_parameter; 9, default_parameter; 10, default_parameter; 11, default_parameter; 12, default_parameter; 13, default_parameter; 14, default_parameter; 15, default_parameter; 16, default_parameter; 17, default_parameter; 18, default_parameter; 19, expression_statement; 20, expression_statement; 21, expression_statement; 22, expression_statement; 23, expression_statement; 24, expression_statement; 25, expression_statement; 26, if_statement; 27, expression_statement; 28, if_statement; 29, expression_statement; 30, if_statement; 31, expression_statement; 32, return_statement; 33, identifier:x; 34, string; 35, identifier:y; 36, string; 37, identifier:size_col; 38, string; 39, identifier:text_col; 40, string; 41, identifier:category_col; 42, string; 43, identifier:possible_categories; 44, None; 45, identifier:filename; 46, None; 47, identifier:config; 48, dictionary; 49, identifier:xscale; 50, None; 51, identifier:yscale; 52, string; 53, identifier:layout; 54, dictionary; 55, identifier:marker; 56, dictionary; 57, identifier:min_size; 58, integer:10; 59, comment:r"""Interactive scatterplot of a DataFrame with the size and color of circles linke to two columns
  
      config keys:
        fillFrame setBackground displaylogo sendData showLink linkText staticPlot scrollZoom plot3dPixelRatio displayModeBar
        showTips workspace doubleClick autosizable editable
  
      layout keys:
        angularaxis annotations autosize bargap bargroupgap barmode barnorm boxgap boxgroupgap boxmode calendar
        direction dragmode font geo height hiddenlabels hiddenlabelssrc hidesources hovermode images legend
        mapbox margin orientation paper_bgcolor plot_bgcolor radialaxis scene separators shapes showlegend sliders smith
        ternary title titlefont updatemenus width xaxis yaxis
  
      marker keys:
        autocolorscale blend border cauto cmax cmin color colorbar colors colorscale colorsrc colorssrc line maxdisplayed
        opacity opacitysrc outliercolor reversescale showscale size sizemax sizemin sizemode sizeref sizesrc symbol symbolsrc
  
      marker['sizeref'] gives the denominator of the circle scaling factor.
        Typically it should be about a tenth of the minimum 'size' column value
  
      >>> from nlpia.data.loaders import get_data
      >>> df = get_data('cities_us_wordvectors_pca2_meta').iloc[:100]
      >>> html = offline_plotly_scatter_bubble(
      ...     df.sort_values('population', ascending=False)[:350].copy().sort_values('population'),
      ...     x='x', y='y',
      ...     size_col='population', text_col='name', category_col='timezone',
      ...     xscale=None, yscale=None,  # 'log' or None
      ...     layout={}, marker={'sizeref': 3000})
      """; 60, assignment; 61, assignment; 62, call; 63, assignment; 64, assignment; 65, call; 66, comparison_operator:config is not None; 67, block; 68, assignment; 69, boolean_operator; 70, block; 71, assignment; 72, boolean_operator; 73, block; 74, else_clause; 75, assignment; 76, call; 77, string_content:x; 78, string_content:y; 79, string_content:size; 80, string_content:text; 81, string_content:category; 82, pair; 83, string_content:log; 84, pair; 85, pair; 86, pair; 87, pair; 88, identifier:config_default; 89, call; 90, identifier:marker_default; 91, dictionary; 92, attribute; 93, argument_list; 94, identifier:size_col; 95, call; 96, identifier:layout_default; 97, dictionary; 98, attribute; 99, argument_list; 100, identifier:config; 101, None; 102, expression_statement; 103, attribute; 104, call; 105, comparison_operator:possible_categories is None; 106, comparison_operator:category_col is not None; 107, if_statement; 108, expression_statement; 109, identifier:possible_categories; 110, conditional_expression:[None] if possible_categories is None else possible_categories; 111, identifier:category_col; 112, comparison_operator:category_col in df; 113, expression_statement; 114, block; 115, identifier:data; 116, dictionary; 117, identifier:offline_plotly_data; 118, argument_list; 119, string; 120, False; 121, string; 122, string; 123, string; 124, False; 125, string; 126, True; 127, string; 128, string; 129, identifier:dict; 130, argument_list; 131, pair; 132, pair; 133, pair; 134, identifier:marker_default; 135, identifier:update; 136, identifier:marker; 137, attribute; 138, argument_list; 139, pair; 140, pair; 141, identifier:layout_default; 142, identifier:update; 143, dictionary_splat; 144, call; 145, identifier:df; 146, identifier:columns; 147, identifier:clean_columns; 148, argument_list; 149, identifier:possible_categories; 150, None; 151, identifier:category_col; 152, None; 153, comparison_operator:category_col in df.columns; 154, block; 155, else_clause; 156, assignment; 157, list; 158, comparison_operator:possible_categories is None; 159, identifier:possible_categories; 160, identifier:category_col; 161, identifier:df; 162, assignment; 163, expression_statement; 164, pair; 165, pair; 166, identifier:data; 167, keyword_argument; 168, keyword_argument; 169, string_content:displaylogo; 170, string_content:hovermode; 171, string_content:closest; 172, string_content:showlegend; 173, string_content:autosize; 174, string_content:sizemode; 175, string_content:area; 176, identifier:DEFAULT_PLOTLY_CONFIG; 177, string; 178, boolean_operator; 179, string; 180, string; 181, string; 182, conditional_expression:int(df[size_col].min() * .8) if size_col else min_size; 183, identifier:marker_default; 184, identifier:pop; 185, string; 186, string; 187, call; 188, string; 189, call; 190, identifier:layout; 191, attribute; 192, argument_list; 193, attribute; 194, identifier:category_col; 195, attribute; 196, expression_statement; 197, block; 198, identifier:possible_categories; 199, call; 200, None; 201, identifier:possible_categories; 202, None; 203, identifier:masks; 204, list_comprehension; 205, assignment; 206, string; 207, list_comprehension; 208, string; 209, call; 210, identifier:filename; 211, identifier:filename; 212, identifier:config; 213, identifier:config_default; 214, string_content:size; 215, identifier:size_col; 216, identifier:min_size; 217, string_content:sizemode; 218, string_content:area; 219, string_content:sizeref; 220, call; 221, identifier:size_col; 222, identifier:min_size; 223, string_content:size; 224, string_content:xaxis; 225, identifier:XAxis; 226, argument_list; 227, string_content:yaxis; 228, identifier:YAxis; 229, argument_list; 230, identifier:config_default; 231, identifier:update; 232, identifier:config; 233, identifier:df; 234, identifier:columns; 235, identifier:df; 236, identifier:columns; 237, assignment; 238, expression_statement; 239, identifier:list; 240, argument_list; 241, call; 242, for_in_clause; 243, identifier:masks; 244, binary_operator:[np.array([True] * len(df))] * len(possible_categories); 245, string_content:data; 246, call; 247, for_in_clause; 248, string_content:layout; 249, identifier:Layout; 250, argument_list; 251, identifier:int; 252, argument_list; 253, keyword_argument; 254, keyword_argument; 255, keyword_argument; 256, keyword_argument; 257, identifier:category_labels; 258, subscript; 259, assignment; 260, call; 261, attribute; 262, argument_list; 263, identifier:label; 264, identifier:possible_categories; 265, list; 266, call; 267, identifier:Scatter; 268, argument_list; 269, tuple_pattern; 270, call; 271, dictionary_splat; 272, binary_operator:df[size_col].min() * .8; 273, identifier:title; 274, identifier:x; 275, identifier:type; 276, identifier:xscale; 277, identifier:title; 278, identifier:y; 279, identifier:type; 280, identifier:yscale; 281, identifier:df; 282, identifier:category_col; 283, identifier:category_labels; 284, call; 285, identifier:set; 286, argument_list; 287, identifier:np; 288, identifier:array; 289, comparison_operator:df[category_col] == label; 290, call; 291, identifier:len; 292, argument_list; 293, keyword_argument; 294, keyword_argument; 295, keyword_argument; 296, keyword_argument; 297, keyword_argument; 298, keyword_argument; 299, identifier:category_name; 300, identifier:mask; 301, identifier:zip; 302, argument_list; 303, identifier:layout_default; 304, call; 305, float:.8; 306, attribute; 307, argument_list; 308, identifier:category_labels; 309, subscript; 310, identifier:label; 311, attribute; 312, argument_list; 313, identifier:possible_categories; 314, identifier:x; 315, attribute; 316, identifier:y; 317, attribute; 318, identifier:text; 319, attribute; 320, identifier:marker; 321, call; 322, identifier:mode; 323, string; 324, identifier:name; 325, call; 326, identifier:possible_categories; 327, identifier:masks; 328, attribute; 329, argument_list; 330, identifier:np; 331, identifier:array; 332, identifier:category_col; 333, identifier:df; 334, identifier:category_col; 335, identifier:np; 336, identifier:array; 337, binary_operator:[True] * len(df); 338, subscript; 339, identifier:values; 340, subscript; 341, identifier:values; 342, subscript; 343, identifier:values; 344, identifier:Marker; 345, argument_list; 346, string_content:markers; 347, identifier:str; 348, argument_list; 349, subscript; 350, identifier:min; 351, list; 352, call; 353, subscript; 354, identifier:mask; 355, subscript; 356, identifier:mask; 357, subscript; 358, identifier:mask; 359, keyword_argument; 360, dictionary_splat; 361, identifier:category_name; 362, identifier:df; 363, identifier:size_col; 364, True; 365, identifier:len; 366, argument_list; 367, identifier:df; 368, identifier:x; 369, identifier:df; 370, identifier:y; 371, identifier:df; 372, identifier:text_col; 373, identifier:size; 374, conditional_expression:df[size_col][mask] if size_col in df.columns else size_col; 375, identifier:marker_default; 376, identifier:df; 377, subscript; 378, comparison_operator:size_col in df.columns; 379, identifier:size_col; 380, subscript; 381, identifier:mask; 382, identifier:size_col; 383, attribute; 384, identifier:df; 385, identifier:size_col; 386, identifier:df; 387, identifier:columns
code: def offline_plotly_scatter_bubble(df, x='x', y='y', size_col='size', text_col='text',
                                    category_col='category', possible_categories=None,
                                    filename=None,
                                    config={'displaylogo': False},
                                    xscale=None, yscale='log',
                                    layout={'hovermode': 'closest', 'showlegend': False, 'autosize': True},
                                    marker={'sizemode': 'area'},
                                    min_size=10,
                                    ):
      r"""Interactive scatterplot of a DataFrame with the size and color of circles linke to two columns
  
      config keys:
        fillFrame setBackground displaylogo sendData showLink linkText staticPlot scrollZoom plot3dPixelRatio displayModeBar
        showTips workspace doubleClick autosizable editable
  
      layout keys:
        angularaxis annotations autosize bargap bargroupgap barmode barnorm boxgap boxgroupgap boxmode calendar
        direction dragmode font geo height hiddenlabels hiddenlabelssrc hidesources hovermode images legend
        mapbox margin orientation paper_bgcolor plot_bgcolor radialaxis scene separators shapes showlegend sliders smith
        ternary title titlefont updatemenus width xaxis yaxis
  
      marker keys:
        autocolorscale blend border cauto cmax cmin color colorbar colors colorscale colorsrc colorssrc line maxdisplayed
        opacity opacitysrc outliercolor reversescale showscale size sizemax sizemin sizemode sizeref sizesrc symbol symbolsrc
  
      marker['sizeref'] gives the denominator of the circle scaling factor.
        Typically it should be about a tenth of the minimum 'size' column value
  
      >>> from nlpia.data.loaders import get_data
      >>> df = get_data('cities_us_wordvectors_pca2_meta').iloc[:100]
      >>> html = offline_plotly_scatter_bubble(
      ...     df.sort_values('population', ascending=False)[:350].copy().sort_values('population'),
      ...     x='x', y='y',
      ...     size_col='population', text_col='name', category_col='timezone',
      ...     xscale=None, yscale=None,  # 'log' or None
      ...     layout={}, marker={'sizeref': 3000})
      """
      config_default = dict(DEFAULT_PLOTLY_CONFIG)
      marker_default = {
          'size': size_col or min_size,
          'sizemode': 'area',
          'sizeref': int(df[size_col].min() * .8) if size_col else min_size}
      marker_default.update(marker)
      size_col = marker_default.pop('size')
      layout_default = {
          'xaxis': XAxis(title=x, type=xscale),
          'yaxis': YAxis(title=y, type=yscale),
      }
      layout_default.update(**layout)
      if config is not None:
          config_default.update(config)
      df.columns = clean_columns(df.columns)
      if possible_categories is None and category_col is not None:
          if category_col in df.columns:
              category_labels = df[category_col]
          else:
              category_labels = np.array(category_col)
          possible_categories = list(set(category_labels))
      possible_categories = [None] if possible_categories is None else possible_categories
      if category_col and category_col in df:
          masks = [np.array(df[category_col] == label) for label in possible_categories]
      else:
          masks = [np.array([True] * len(df))] * len(possible_categories)
      data = {'data': [
              Scatter(x=df[x][mask].values,
                      y=df[y][mask].values,
                      text=df[text_col][mask].values,
                      marker=Marker(size=df[size_col][mask] if size_col in df.columns else size_col,
                                    **marker_default),
                      mode='markers',
                      name=str(category_name)) for (category_name, mask) in zip(possible_categories, masks)
              ],
              'layout': Layout(**layout_default)
              }
      return offline_plotly_data(data, filename=filename, config=config_default)