@@ -158,19 +158,36 @@ def strip_style(self):
158
158
for plotly_dict in self :
159
159
plotly_dict .strip_style ()
160
160
161
- def get_data (self ):
162
- """Returns the JSON for the plot with non-data elements stripped."""
161
+ def get_data (self , flatten = False ):
162
+ """
163
+ Returns the JSON for the plot with non-data elements stripped.
164
+
165
+ Flattening may increase the utility of the result.
166
+
167
+ :param (bool) flatten: {'a': {'b': ''}} --> {'a.b': ''}
168
+ :returns: (dict|list) Depending on (flat|unflat)
169
+
170
+ """
163
171
self .to_graph_objs ()
164
172
l = list ()
165
173
for _plotlydict in self :
166
- l += [_plotlydict .get_data ()]
174
+ l += [_plotlydict .get_data (flatten = flatten )]
167
175
del_indicies = [index for index , item in enumerate (self )
168
176
if len (item ) == 0 ]
169
177
del_ct = 0
170
178
for index in del_indicies :
171
179
del self [index - del_ct ]
172
180
del_ct += 1
173
- return l
181
+
182
+ if flatten :
183
+ d = {}
184
+ for i , e in enumerate (l ):
185
+ for k , v in e .items ():
186
+ key = "{0}.{1}" .format (i , k )
187
+ d [key ] = v
188
+ return d
189
+ else :
190
+ return l
174
191
175
192
def validate (self , caller = True ):
176
193
"""Recursively check the validity of the entries in a PlotlyList.
@@ -425,6 +442,8 @@ def strip_style(self):
425
442
else :
426
443
try :
427
444
if INFO [obj_key ]['keymeta' ][key ]['key_type' ] == 'style' :
445
+
446
+ # TODO: use graph_objs_tools.value_is_data
428
447
if isinstance (self [key ], six .string_types ):
429
448
del self [key ]
430
449
elif not hasattr (self [key ], '__iter__' ):
@@ -433,19 +452,25 @@ def strip_style(self):
433
452
# print("'type' not in {0} for {1}".format(obj_key, key))
434
453
pass
435
454
436
- def get_data (self ):
455
+ def get_data (self , flatten = False ):
437
456
"""Returns the JSON for the plot with non-data elements stripped."""
438
457
self .to_graph_objs ()
439
458
class_name = self .__class__ .__name__
440
459
obj_key = NAME_TO_KEY [class_name ]
441
460
d = dict ()
442
461
for key , val in list (self .items ()):
443
462
if isinstance (val , (PlotlyDict , PlotlyList )):
444
- d [key ] = val .get_data ()
463
+ sub_data = val .get_data (flatten = flatten )
464
+ if flatten :
465
+ for sub_key , sub_val in sub_data .items ():
466
+ key_string = "{0}.{1}" .format (key , sub_key )
467
+ d [key_string ] = sub_val
468
+ else :
469
+ d [key ] = sub_data
445
470
else :
446
471
try :
447
472
# TODO: Update the JSON
448
- if INFO [ obj_key ][ 'keymeta' ][ key ][ 'key_type' ] == 'data' :
473
+ if graph_objs_tools . value_is_data ( obj_key , key , val ) :
449
474
d [key ] = val
450
475
except KeyError :
451
476
pass
@@ -454,8 +479,6 @@ def get_data(self):
454
479
if isinstance (d [key ], (dict , list )):
455
480
if len (d [key ]) == 0 :
456
481
del d [key ]
457
- if len (d ) == 1 :
458
- d = list (d .values ())[0 ]
459
482
return d
460
483
461
484
def to_graph_objs (self , caller = True ):
@@ -860,6 +883,42 @@ def to_graph_objs(self, caller=True): # TODO TODO TODO! check logic!
860
883
)
861
884
super (Data , self ).to_graph_objs (caller = caller )
862
885
Data .to_graph_objs = to_graph_objs # override method!
886
+
887
+ def get_data (self , flatten = False ):
888
+ """
889
+
890
+ :param flatten:
891
+ :return:
892
+
893
+ """
894
+ if flatten :
895
+ self .to_graph_objs ()
896
+ data = [v .get_data (flatten = flatten ) for v in self ]
897
+ d = {}
898
+ taken_names = []
899
+ for i , trace in enumerate (data ):
900
+
901
+ # we want to give the traces helpful names
902
+ # however, we need to be sure they're unique too...
903
+ trace_name = trace .pop ('name' , 'trace_{0}' .format (i ))
904
+ if trace_name in taken_names :
905
+ j = 1
906
+ new_trace_name = "{0}_{1}" .format (trace_name , j )
907
+ while new_trace_name in taken_names :
908
+ new_trace_name = "{0}_{1}" .format (trace_name , j )
909
+ j += 1
910
+ trace_name = new_trace_name
911
+ taken_names .append (trace_name )
912
+
913
+ # finish up the dot-concatenation
914
+ for k , v in trace .items ():
915
+ key = "{0}.{1}" .format (trace_name , k )
916
+ d [key ] = v
917
+ return d
918
+ else :
919
+ return super (Data , self ).get_data (flatten = flatten )
920
+ Data .get_data = get_data
921
+
863
922
return Data
864
923
865
924
Data = get_patched_data_class (Data )
@@ -934,6 +993,26 @@ def print_grid(self):
934
993
print (grid_str )
935
994
Figure .print_grid = print_grid
936
995
996
+ def get_data (self , flatten = False ):
997
+ """
998
+ Returns the JSON for the plot with non-data elements stripped.
999
+
1000
+ Flattening may increase the utility of the result.
1001
+
1002
+ :param (bool) flatten: {'a': {'b': ''}} --> {'a.b': ''}
1003
+ :returns: (dict|list) Depending on (flat|unflat)
1004
+
1005
+ """
1006
+ self .to_graph_objs ()
1007
+ return self ['data' ].get_data (flatten = flatten )
1008
+ Figure .get_data = get_data
1009
+
1010
+ def to_dataframe (self ):
1011
+ data = self .get_data (flatten = True )
1012
+ from pandas import DataFrame , Series
1013
+ return DataFrame (dict ([(k , Series (v )) for k , v in data .items ()]))
1014
+ Figure .to_dataframe = to_dataframe
1015
+
937
1016
def append_trace (self , trace , row , col ):
938
1017
""" Helper function to add a data traces to your figure
939
1018
that is bound to axes at the row, col index.
0 commit comments