-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Sunburst/treemap path #2006
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sunburst/treemap path #2006
Changes from 18 commits
4ac1efb
c619e28
10668b6
edfcced
1f3b8da
8cb9d99
cd500a5
c233220
edefabf
41c8d30
2952fe6
c6b7243
be3b622
7f2920b
8519302
437bbd7
fb9d992
a57b027
bf8da4b
9e23890
f67602f
6b6a105
9996731
f3e7e27
8cd227a
8b66c90
19b81ac
ba6ec19
c0cbce0
57503b4
0ab2afd
0d86998
d63d4bd
9b217f8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1007,6 +1007,99 @@ def build_dataframe(args, attrables, array_attrables): | |
return args | ||
|
||
|
||
def _discrete_agg(x): | ||
if len(x) == 1: | ||
return x.iloc[0] | ||
else: | ||
return "" | ||
|
||
|
||
def process_dataframe_hierarchy(args): | ||
""" | ||
Build dataframe for sunburst or treemap when the path argument is provided. | ||
""" | ||
df = args["data_frame"] | ||
path = args["path"][::-1] | ||
|
||
# ------------ Define aggregation functions -------------------------------- | ||
lambda_discrete = _discrete_agg | ||
agg_f = {} | ||
aggfunc_color = None | ||
if args["values"]: | ||
try: | ||
df[args["values"]] = pd.to_numeric(df[args["values"]]) | ||
except ValueError: | ||
raise ValueError( | ||
"Column `%s` of `df` could not be converted to a numerical data type." | ||
% args["values"] | ||
) | ||
|
||
if args["color"]: | ||
if args["color"] == args["values"]: | ||
aggfunc_color = "sum" | ||
nicolaskruchten marked this conversation as resolved.
Show resolved
Hide resolved
|
||
count_colname = args["values"] | ||
else: | ||
if args["color"]: # color passed but not value | ||
# we need a count column for the weighted mean of color | ||
# trick to be sure the col name is unused: take the sum of existing names | ||
count_colname = "".join([str(el) for el in list(df.columns)]) | ||
# we can modify df because it's a copy of the px argument | ||
df[count_colname] = 1 | ||
|
||
if args["color"]: | ||
if df[args["color"]].dtype.kind not in "bifc": | ||
aggfunc_color = lambda_discrete | ||
elif not aggfunc_color: | ||
aggfunc_color = lambda x: np.average( | ||
nicolaskruchten marked this conversation as resolved.
Show resolved
Hide resolved
|
||
x, weights=df.loc[x.index, count_colname] | ||
) | ||
agg_f[args["color"]] = aggfunc_color | ||
if args["color"] or args["values"]: | ||
agg_f[count_colname] = "sum" | ||
|
||
# Other columns (for color, hover_data, custom_data etc.) | ||
cols = list(set(df.columns).difference(path)) | ||
for col in cols: # for hover_data, custom_data etc. | ||
if col not in agg_f: | ||
agg_f[col] = lambda_discrete | ||
# ---------------------------------------------------------------------------- | ||
|
||
df_all_trees = pd.DataFrame(columns=["labels", "parent", "id"] + cols) | ||
# Set column type here (useful for continuous vs discrete colorscale) | ||
for col in cols: | ||
df_all_trees[col] = df_all_trees[col].astype(df[col].dtype) | ||
for i, level in enumerate(path): | ||
df_tree = pd.DataFrame(columns=df_all_trees.columns) | ||
if not agg_f: | ||
dfg = df.groupby(path[i:]).sum(numerical_only=True) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. under what circumstances do we do this, and what's the reasoning? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it's if neither There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I could get rid of this part with the |
||
else: | ||
dfg = df.groupby(path[i:]).agg(agg_f) | ||
dfg = dfg.reset_index() | ||
df_tree["labels"] = dfg[level].copy().astype(str) | ||
df_tree["parent"] = "" | ||
df_tree["id"] = dfg[level].copy().astype(str) | ||
if i < len(path) - 1: | ||
j = i + 1 | ||
while j < len(path): | ||
df_tree["parent"] += dfg[path[j]].copy().astype(str) | ||
df_tree["id"] += dfg[path[j]].copy().astype(str) | ||
nicolaskruchten marked this conversation as resolved.
Show resolved
Hide resolved
|
||
j += 1 | ||
else: | ||
df_tree["parent"] = "" | ||
nicolaskruchten marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
if cols: | ||
df_tree[cols] = dfg[cols] | ||
df_all_trees = df_all_trees.append(df_tree, ignore_index=True) | ||
|
||
# Now modify arguments | ||
args["data_frame"] = df_all_trees | ||
args["path"] = None | ||
args["ids"] = "id" | ||
args["names"] = "labels" | ||
args["parents"] = "parent" | ||
return args | ||
|
||
|
||
def infer_config(args, constructor, trace_patch): | ||
# Declare all supported attributes, across all plot types | ||
attrables = ( | ||
|
@@ -1015,9 +1108,9 @@ def infer_config(args, constructor, trace_patch): | |
+ ["names", "values", "parents", "ids"] | ||
+ ["error_x", "error_x_minus"] | ||
+ ["error_y", "error_y_minus", "error_z", "error_z_minus"] | ||
+ ["lat", "lon", "locations", "animation_group"] | ||
nicolaskruchten marked this conversation as resolved.
Show resolved
Hide resolved
|
||
+ ["lat", "lon", "locations", "animation_group", "path"] | ||
) | ||
array_attrables = ["dimensions", "custom_data", "hover_data"] | ||
array_attrables = ["dimensions", "custom_data", "hover_data", "path"] | ||
group_attrables = ["animation_frame", "facet_row", "facet_col", "line_group"] | ||
all_attrables = attrables + group_attrables + ["color"] | ||
group_attrs = ["symbol", "line_dash"] | ||
|
@@ -1026,6 +1119,8 @@ def infer_config(args, constructor, trace_patch): | |
all_attrables += [group_attr] | ||
|
||
args = build_dataframe(args, all_attrables, array_attrables) | ||
if constructor in [go.Treemap, go.Sunburst] and args["path"] is not None: | ||
args = process_dataframe_hierarchy(args) | ||
|
||
attrs = [k for k in attrables if k in args] | ||
grouped_attrs = [] | ||
|
Uh oh!
There was an error while loading. Please reload this page.