def ts_gradient(dfg, type_trans, avg_month): """ Creates a timeseries plot where all years are ploted simultaneously Args: dfg: dataframe to use type_trans: type of transaction [Income/Expense] avg_month: month to use in time average Returns: the plotly plot as html-div format """ if type_trans in [c.names.INCOMES, c.names.EXPENSES]: df = dfg[dfg[c.cols.TYPE] == type_trans].copy() else: df = dfg.copy() mfilter = df[c.cols.TYPE] == c.names.EXPENSES df.loc[mfilter, c.cols.AMOUNT] = -df.loc[mfilter, c.cols.AMOUNT] df = u.group_df_by(df, "M") if df.shape[0] == 0: return {} df = u.time_average(df, avg_month) max_width = 5 color_name = { c.names.INCOMES: "green", c.names.EXPENSES: "red" }.get(type_trans, "amber") data = [] for year in sorted(set(df.index.year), reverse=False): index_color = max(100, 900 - 200 * (max(df.index.year) - year)) color = u.get_colors((color_name, index_color)) df_aux = df[df.index.year == year] data.append( go.Scatter( x=df_aux.index.month, y=df_aux[c.cols.AMOUNT].values, line={ "width": min(0.5 * (year - min(df.index.year)) + 1, max_width) }, marker={"color": color}, name=year, mode="lines", )) layout = go.Layout(title="Time comparison ({})".format(type_trans), hovermode="closest") return go.Figure(data=data, layout=layout)
def dist_plot(dfg): """ Creates a distribution plot with expenses, incomes and ebit Args: dfg: dataframe to use Returns: the plotly plot as html-div format """ dfe = u.group_df_by(dfg[dfg[c.cols.TYPE] == c.names.EXPENSES], "M") dfi = u.group_df_by(dfg[dfg[c.cols.TYPE] == c.names.INCOMES], "M") df_baii = dfi - dfe iter_data = [ (df_baii, c.names.EBIT, c.colors.EBIT), (dfe, c.names.EXPENSES, c.colors.EXPENSES), (dfi, c.names.INCOMES, c.colors.INCOMES), ] # Generate traces to show. This allow to disable traces if there is no data data, names, colors = [], [], [] for df, name, color in iter_data: # Some data needed if (df[c.cols.AMOUNT].sum() > 0) and (len(df[c.cols.AMOUNT].unique()) > 1): data.append(df[c.cols.AMOUNT].fillna(0).tolist()) names.append(name) colors.append(color) if not data: return {} fig = FF.create_distplot(data, names, colors=colors, bin_size=100) fig["layout"].update(title="Incomes, Expenses and EBIT distribution") return fig
def plot_expenses_vs_liquid(df_liquid_in, df_trans_in, avg_month, show_rec=True, height=None): """ Creates a plot to compare liquid and expenses Args: df_liq_in: dataframe with liquid info df_trans_in: dataframe with transactions avg_month: month to use in time average show_rec: bool for show/hide recommended liquids height: height of the plot Returns: the plotly plot as html-div format """ df_l = df_liquid_in.set_index(c.cols.DATE).copy() df_l = u.time_average(df_l.fillna(0), avg_month) df_t = u.group_df_by( df_trans_in[df_trans_in[c.cols.TYPE] == c.names.EXPENSES], "M") df_t = u.time_average(df_t, avg_month) iter_data = [ (df_t, df_t[c.cols.AMOUNT], c.names.EXPENSES, c.colors.EXPENSES), (df_l, df_l[c.names.TOTAL], c.names.LIQUID, c.colors.LIQUID), (df_t, MONTHS_MIN * df_t[c.cols.AMOUNT], c.names.LIQUID_MIN_REC, c.colors.LIQUID_MIN_REC), (df_t, MONTHS_REC * df_t[c.cols.AMOUNT], c.names.LIQUID_REC, c.colors.LIQUID_REC), ] if not show_rec: iter_data = iter_data[:2] data = [ go.Scatter(x=df.index, y=y, name=name, marker={"color": color}, mode="lines") for df, y, name, color in iter_data ] layout = go.Layout(title="Liquid vs Expenses", showlegend=show_rec, height=height) return go.Figure(data=data, layout=layout)
def plot_months(df_liquid_in, df_trans_in, avg_month, show_rec=True, height=None): """ Creates a plot to compare liquid and expenses Args: df_liq_in: dataframe with liquid info df_trans_in: dataframe with transactions avg_month: month to use in time average show_rec: bool for show/hide recommended liquids height: height of the plot Returns: the plotly plot as html-div format """ df_l = df_liquid_in.set_index(c.cols.DATE).copy() df_l = u.time_average(df_l.fillna(0), avg_month) df_t = u.group_df_by( df_trans_in[df_trans_in[c.cols.TYPE] == c.names.EXPENSES], "M") df_t = u.time_average(df_t, avg_month) serie = df_l[c.names.TOTAL] / df_t[c.cols.AMOUNT] iter_data = [ (serie, "Months", c.colors.LIQUID), ([MONTHS_MIN] * len(serie), "Minimum months of liquid", c.colors.LIQUID_MIN_REC), ([MONTHS_REC] * len(serie), "Recommended months of liquid", c.colors.LIQUID_REC), ] if not show_rec: iter_data = iter_data[:1] data = [ go.Scatter(x=serie.index, y=y, name=name, marker={"color": color}, mode="lines") for y, name, color in iter_data ] layout = go.Layout(title="Survival months with current liquid", height=height) return go.Figure(data=data, layout=layout)
def passive_income_vs_expenses(df_wor_in, df_trans_in, avg_month, smooth): """ Compares what can be generated with passive income to expanses Args: df_wor_in: dataframe with investment worth df_trans_in: dataframe with transactions avg_month: month to use in time average smooth: bool to allow/disable passive smoothing Returns: the plotly plot as html-div format """ dfw = df_wor_in.set_index(c.cols.DATE)[[c.names.TOTAL]] if smooth: dfw = u.time_average(dfw, avg_month) dfe = u.group_df_by( df_trans_in[df_trans_in[c.cols.TYPE] == c.names.EXPENSES], "M") dfe = u.time_average(dfe, avg_month) data = [ go.Scatter( x=dfw.index, y=dfw[c.names.TOTAL] * 0.04 / 12, name="Passive income", marker={"color": c.colors.INCOMES_PASSIVE}, ), go.Scatter(x=dfe.index, y=dfe[c.cols.AMOUNT], name="Expenses", marker={"color": c.colors.EXPENSES}), ] layout = go.Layout(title="Passive income vs expenses", barmode="stack") return go.Figure(data=data, layout=layout)
def get_heatmap(dfg, type_trans): """ Creates a heatmap with expenses or incomes Args: dfg: dataframe to use type_trans: type of transaction [Income/Expense] Returns: the plotly plot as html-div format """ df = u.group_df_by(dfg[dfg[c.cols.TYPE] == type_trans], "M") # No data no fun if df.shape[0] < 2: return {} df[c.cols.YEAR], df[c.cols.MONTH_DATE] = df.index.year, df.index.month df = df.pivot(c.cols.MONTH_DATE, c.cols.YEAR, c.cols.AMOUNT).sort_index(ascending=False) # Fix month names df.index = [month_abbr[x] for x in df.index] cmap = {c.names.INCOMES: "Greens", c.names.EXPENSES: "YlOrRd"}[type_trans] data = go.Heatmap(x=df.columns, y=df.index, z=df.values, colorscale=cmap, reversescale=True, showscale=False) layout = go.Layout(title="Heatmap ({})".format(type_trans)) return go.Figure(data=[data], layout=layout)