Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added __pycache__/eda_view.cpython-311.pyc
Binary file not shown.
Binary file added __pycache__/prediction_view.cpython-311.pyc
Binary file not shown.
251 changes: 251 additions & 0 deletions eda_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
import altair as alt
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import streamlit as st
import seaborn as sns
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots



def run(df):
# LAYOUT DEL DASHBOARD
# Primera fila con una sola columna
row1,row12 = st.columns((2,1), gap='medium')
# Segunda fila con dos columnas
col1, col2 = st.columns(2)
# Tercera fila con dos columnas
col3, col4, col5, col6 = st.columns(4)
# quarta fila con una sola columna
row21 = st.container()
# Quinta fila con una sola columna
row2 = st.container()

# Añadimos contenido
row1.header('Gestión de incidencias - Overview')

total_incidencias = df['task_id'].nunique() # Mostrar el número total de incidencias
row12.markdown(f'<div style="border:1px solid black; padding:10px;">Número total de incidencias: {total_incidencias}</div>', unsafe_allow_html=True)

# Insertar graficos
variable = col1.selectbox('Seleccione la variable para agrupar:', ['priority', 'has_breached', 'assignment_group', 'company', 'contact_type','impact'])
incidencias_timeline_fig = incidencias_timeline(df, variable) # grafico de barras, analisis temporal
tiempo_trabajado_fig = tiempo_trabajado(df, variable) # priority vs time worked
col1.plotly_chart(incidencias_timeline_fig)
col2.plotly_chart(tiempo_trabajado_fig)

# Pie charts
pie1 = pie_chart_menos_24h(df)
pie2 = pie_chart_mas_24h(df)
pie3 = pie_chart_reasigned(df)
pie4 = pie_chart_not_reasigned(df)

col3.plotly_chart(pie1)
col4.plotly_chart(pie2)
col5.plotly_chart(pie3)
col6.plotly_chart(pie4)


var_select = col4.selectbox('Seleccione la variable para agrupar:', ['assignment_group', 'company', 'priority'])
contact_type_fig = contact_type(df, var_select)
row21.plotly_chart(contact_type_fig)

variable_select = row2.selectbox('Seleccione la variable para agrupar:', ['assignment_group', 'company', 'contact_type'])
table = tabla(df, variable_select)
row2.table(table)


# FUNCIONES GRAFICOS ---------------------------------------------------------------------------------
def incidencias_timeline(df, variable):
df['end_time'] = pd.to_datetime(df['end_time'])
df.set_index('end_time', inplace=True)

grouped = df.groupby(variable).resample('M')['task_id'].nunique().reset_index()

# Crear un gráfico de barras apilado con colores basados en la variable seleccionada
incidencias_timeline_fig = px.bar(grouped, x='end_time', y='task_id', color=variable, title='Número de incidencias por mes',
labels={'task_id':'Número de incidencias'}, height=400)
incidencias_timeline_fig.update_layout(barmode='stack')
incidencias_timeline_fig.update_xaxes(title_text='Mes y año de finalización')
#st.plotly_chart(incidencias_timeline_fig)
return incidencias_timeline_fig

def tiempo_trabajado(df, variable):
tiempo_trabajado_fig = px.bar(df, y='time_worked', x='priority', color=variable)
tiempo_trabajado_fig.update_layout(
title='Relación entre la prioridad y el tiempo trabajado',
yaxis_title='Tiempo trabajado',
xaxis_title='Prioridad'
)
#st.plotly_chart(tiempo_trabajado_fig)
return tiempo_trabajado_fig

def tabla(df, variable_select):
priority_counts = df.groupby([variable_select, 'priority']).size().reset_index(name='counts')
total_counts = df.groupby(variable_select).size()
priority_counts['percentage'] = priority_counts.apply(lambda row: (row['counts'] / total_counts[row[variable_select]]) * 100, axis=1)
priority_counts['percentage'] = priority_counts['percentage'].round(2)
priority_counts['percentage'] = priority_counts['percentage'].astype(str) + '%'
pivot_table = priority_counts.pivot(index=variable_select, columns='priority', values='percentage')
#pivot_columns = pivot_table.columns.tolist()

print(pivot_table)
column_names = [variable_select, '% de incidencias', 'Media business duration',
'% incumplimiento SLA', 'Critical', 'High', 'Moderate', 'Low','Planning'] #+ pivot_columns

# column_names = pd.MultiIndex.from_tuples([(None, variable_select),
# (None,'% de incidencias'),
# (None, 'Media business duration'),
# (None, '% infracción SLA'),
# ('Priority', 'Critical'), ('Priority', 'High'),
# ('Priority', 'Moderate'), ('Priority', 'Low'), ('Priority', 'Planning')])


# tabla para representar la info
grouped_table = df.groupby(variable_select).agg({'task_id': lambda x: x.count() / df['task_id'].count() * 100,
'business_duration': 'mean',
'has_breached': lambda x: x.sum() / x.count() * 100})
grouped_table = pd.merge(grouped_table, pivot_table, on=variable_select, how='left')

# has_brached = yes -> % de incidencias que han incumplido el SLA
grouped_table['task_id'] = grouped_table['task_id'].round(2)
grouped_table['task_id'] = grouped_table['task_id'].astype(str) + '%'
grouped_table['business_duration'] = grouped_table['business_duration'].round(0).astype(int)
grouped_table['has_breached'] = grouped_table['has_breached'].round(2)
grouped_table['has_breached'] = grouped_table['has_breached'].astype(str) + '%' # ponerlo en modo de barra si se puede

grouped_table = grouped_table.reset_index()
grouped_table.columns = column_names

grouped_table.set_index(variable_select, inplace=True)
grouped_table['% incumplimiento SLA'] = grouped_table['% incumplimiento SLA'].apply(add_warning_icon)
grouped_table = grouped_table.fillna('0%') # if 'Critical', 'High', 'Moderate', 'Low','Planning' == nana -> 0%

# apply styles
grouped_table = grouped_table.style.applymap(color_cell_priority).set_properties(**{'text-align': 'center'}).set_table_styles([dict(selector='th', props=[('background', '#54B4CE'), ('color', 'white')])])
#st.table(grouped_table)
return grouped_table

def contact_type(df, var_select):
fig3 = px.bar(df, x=var_select, y='task_id', color='contact_type', labels={'task_id':'Número de incidencias'})
fig3.update_layout(
title= f'{var_select} vs tipo de contacto',
xaxis_title=var_select,
yaxis_title='Número de incidencias'
)
ax = plt.gca() # get current axes
ax.set_yticklabels([])
fig3.update_layout(barmode='stack')
#st.plotly_chart(fig3)
return fig3

#def pie_charts(df):
selection_variable = st.selectbox('Seleccione la variable para agrupar:', ['reassingment_count_bool','u_24_7'])
contact_types = df['contact_type'].unique()

fig6 = make_subplots(rows=1, cols=len(contact_types), subplot_titles=contact_types, specs=[[{'type':'domain'}]*len(contact_types)])

for i, contact_type in enumerate(contact_types):
data = df[df['contact_type'] == contact_type][selection_variable].value_counts()
fig6.add_trace(go.Pie(labels=data.index, values=data, name=contact_type), 1, i+1)

fig6.update_layout(height=600, width=900, title_text=f'Tipo de contacto vs {selection_variable}',
legend_title_text=f'{selection_variable}', title_x=0.5, title_y=0.95)
st.plotly_chart(fig6)

def pie_chart_menos_24h(df):

df['less_24h'] = df['u_24_7'].apply(lambda x: 1 if x == True else 0) # 1 si ha sido resuelta en menos de 24h

# guardar en una variable el % de incidencias que han sido resueltas en menos de 24h
porcentaje_less = df['less_24h'].sum() / df['less_24h'].count() * 100

df_filtered = df[df['less_24h'] == 1] # solo aquellas incidencias que han sido resueltas en menos de 24h

# un único pie chart coloreado por tipo de contacto, indicando el % de incidencias que han sido resueltas en menos de 24h
pie = px.pie(df_filtered, names='contact_type', title=f'Incidencias resueltas en menos de 24h - {porcentaje_less:.2f}%',
labels={'contact_type':'Tipo de contacto'}, height=400)

#st.plotly_chart(pie)
return pie

def pie_chart_mas_24h(df):

df['more_24h'] = df['u_24_7'].apply(lambda x: 1 if x == False else 0) # 1 si ha sido resuelta en menos de 24h

# guardar en una variable el % de incidencias que han sido resueltas en menos de 24h
porcentaje_more = df['more_24h'].sum() / df['less_24h'].count() * 100

df_filtered = df[df['more_24h'] == 1] # solo aquellas incidencias que han sido resueltas en menos de 24h

# un único pie chart coloreado por tipo de contacto, indicando el % de incidencias que han sido resueltas en menos de 24h
pie = px.pie(df_filtered, names='contact_type', title=f'Incidencias resueltas en más de 24h - {porcentaje_more:.2f}%',
labels={'contact_type':'Tipo de contacto'}, height=400)

return pie

def pie_chart_reasigned(df):


# guardar en una variable el % de incidencias que han sido resueltas en menos de 24h
porcentaje_reasigned = df['reassingment_count_bool'].sum() / df['reassingment_count_bool'].count() * 100

df_filtered = df[df['reassingment_count_bool'] == 1] # solo aquellas incidencias que han sido resueltas en menos de 24h

# un único pie chart coloreado por tipo de contacto, indicando el % de incidencias que han sido resueltas en menos de 24h
pie = px.pie(df_filtered, names='contact_type', title=f'Incidencias reasignadas - {porcentaje_reasigned:.2f}%',
labels={'contact_type':'Tipo de contacto'}, height=400)

return pie

def pie_chart_not_reasigned(df):
# cambiar los 1 por 0 y los 0 por 1
df['reassingment_count_bool'] = df['reassingment_count_bool'].apply(lambda x: 0 if x == 1 else 1)
# guardar en una variable el % de incidencias que han sido resueltas en menos de 24h
porcentaje_not_reasigned = df['reassingment_count_bool'].sum() / df['reassingment_count_bool'].count() * 100

df_filtered = df[df['reassingment_count_bool'] == 1] # solo aquellas incidencias que han sido resueltas en menos de 24h

# un único pie chart coloreado por tipo de contacto, indicando el % de incidencias que han sido resueltas en menos de 24h
pie = px.pie(df_filtered, names='contact_type', title=f'Incidencias no reasignadas - {porcentaje_not_reasigned:.2f}%',
labels={'contact_type':'Tipo de contacto'}, height=400)

return pie



# FUNCIONES AUXILIARES ---------------------------------------------------------------------------------

def add_warning_icon(val):
if isinstance(val, str) and val.endswith('%'):
percentage = float(val.rstrip('%'))
if percentage > 10:
return f'{val} ⚠️'
return val

def color_cell_priority(val):
priority = ['Critical', 'High', 'Moderate', 'Low', 'Planning']
if isinstance(val, str):
if val in priority:
percentage = float(val.rstrip('%'))
if percentage > 50:
return 'background-color: yellow'
return ''

def set_page_layout(page_width='70%', page_align='center'):
st.markdown(
f"""
<style>
.reportview-container .main .block-container{{
max-width: {page_width};
padding-top: 1rem;
padding-right: 1rem;
padding-left: 1rem;
margin-{page_align}-auto;
}}
</style>
""",
unsafe_allow_html=True,
)
23 changes: 23 additions & 0 deletions prediction_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import altair as alt
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import streamlit as st


def run():
# boton en el centro para crear una nueva incidencia que abra un formulario con campos basicos
if st.button('Crear una nueva incidencia'):
with st.form(key='my_form'):
st.write('Cree una nueva incidencia:')

# Aquí puedes agregar los campos que necesites para tu formulario
campo1 = st.text_input(label='Campo 1')
campo2 = st.text_input(label='Campo 2')
campo3 = st.text_input(label='Campo 3')

# Botón de envío del formulario
submit_button = st.form_submit_button(label='Enviar')

# botón para cancelr el formulario
cancel_button = st.form_submit_button(label='Cancelar')
12 changes: 12 additions & 0 deletions sentiment-analysis-view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import altair as alt
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib as mpl
mpl.use('TkAgg')
import streamlit as st
import seaborn as sns
import plotly.express as px



64 changes: 28 additions & 36 deletions streamlit_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,31 @@
import numpy as np
import pandas as pd
import streamlit as st

"""
# Welcome to Streamlit!

Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
forums](https://discuss.streamlit.io).

In the meantime, below is an example of what you can do with just a few lines of code:
"""

num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
num_turns = st.slider("Number of turns in spiral", 1, 300, 31)

indices = np.linspace(0, 1, num_points)
theta = 2 * np.pi * num_turns * indices
radius = indices

x = radius * np.cos(theta)
y = radius * np.sin(theta)

df = pd.DataFrame({
"x": x,
"y": y,
"idx": indices,
"rand": np.random.randn(num_points),
})

st.altair_chart(alt.Chart(df, height=700, width=700)
.mark_point(filled=True)
.encode(
x=alt.X("x", axis=None),
y=alt.Y("y", axis=None),
color=alt.Color("idx", legend=None, scale=alt.Scale()),
size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
))
import eda_view as view1
import prediction_view as view2
import streamlit_option_menu
from streamlit_option_menu import option_menu

st.set_page_config(layout="wide",
initial_sidebar_state="expanded")
alt.themes.enable("dark")

with st.sidebar:
st.title("Gestión de incidencias")
selected = option_menu(
menu_title = "Menu",
options = ['Overview', 'Nueva incidencia'],
icons = ["house","gear"],
menu_icon = "cast",
default_index = 0,
)

#df = pd.read_excel('/Users/carlotapersonal/Library/CloudStorage/OneDrive-UFV/CURSO_5/PFG/Code/proyecto-fin-de-grado-2024-2-carlotagomezr/data-analysis/eda/dataset_post_EDA.xlsx')
df = pd.read_excel('/Users/carlotro/Desktop/Escritorio/Personal-Carlota/UFV/PFG/APP-REPO/dataset_post_EDA.xlsx')
df['reassingment_count_bool'] = df['reassignment_count'].apply(lambda x: 1 if x > 0 else 0) # indicar si ha habido reasignacion o no


if selected == 'Overview':
view1.run(df)
elif selected == 'Nueva incidencia':
view2.run(df)