Análisis de los resultados de las evaluaciones con usuarios de los prototipos RelintBot1 y RelintBo2

In [137]:
import pandas as pd
import numpy as np 
from matplotlib import pyplot as plt

Cargar el fichero

In [138]:
# Todos los datos
data = pd.read_excel('./answers/cleaned.xlsx')

# Evaluación de  RelintBot1
rb1_data = data[data['prototype']=='RelintBot1']

# Evaluación de RelintBot2
rb2_data = data[data['prototype']=='RelintBot2']
data.head(5)
Out[138]:
timestamp prototype user age sex mother_tongue t1_correct_answers t2_completed t2_messages t2_chars ... sus_1 sus_2 sus_3 sus_4 sus_5 sus_6 sus_7 sus_8 sus_9 sus_10
0 2020-04-07 12:22:49.360 RelintBot1 1 23 Hombre Español 3 1.0 105.0 ... 3 1 4 2 4 3 5 3 3 1
1 2020-04-07 12:38:23.380 ReintBot2 1 23 Hombre Español 2 2.0 99.0 ... 3 1 4 2 4 1 5 2 3 2
2 2020-04-07 12:54:30.230 ReintBot2 2 22 Hombre Español 5 3.0 141.0 ... 3 1 5 1 4 1 5 1 5 1
3 2020-04-07 13:12:56.120 RelintBot1 2 22 Hombre Español 3 No NaN NaN ... 2 4 2 1 2 3 4 4 5 1
4 2020-04-07 13:53:05.090 RelintBot1 3 21 Hombre Francés 3 No NaN NaN ... 3 2 4 2 3 2 4 2 4 2

5 rows × 23 columns

Usuarios

Edad

In [139]:
# Extraer variable
age = rb1_data['age'] 

# Diagrama de Cajas y bigotes
fig1, ax1 = plt.subplots(figsize=(6,5)) 
ax1.boxplot(age, vert=False, labels=['Edad'])
plt.show()
In [140]:
print("Media = {:.2f}".format(np.average(np.array(list(age)))))
print("Mediana = {:.0f}".format(np.median(np.array(list(age)))))
print("Mínimo = {:.0f}".format(min(list(age))))
print("Máximo = {:.0f}".format(max(list(age))))
Media = 22.27
Mediana = 22
Mínimo = 20
Máximo = 29

Sexo

In [141]:
# Extraer valores
sex = rb1_data['sex']
male = len(list(filter(lambda s: s == 'Hombre', sex)))
female = len(sex) - male

# Diagrama de sectores
labels = ['Hombre', 'Mujer']
colors = ['C0', 'red']
sizes = [male, female]
explode = (0, 0.1) 

fig1, ax1 = plt.subplots(figsize=(6,6))
#ax1.set_title('Sexo')
ax1.pie(sizes, labels=labels, autopct='%2.2f%%', colors=colors, explode=explode, startangle=90)
ax1.axis('equal') 

plt.show()

Lengua Materna

In [142]:
# Extraer variable 
mother_tongue = list(rb1_data['mother_tongue'])
all_languages = ['Español', 'Inglés', 'Francés', 'Alemán', 'Italiano', 'Otra']
count = list(map(lambda lang: mother_tongue.count(lang), all_languages))

# Diagrama de Pareto
fig1, ax1 = plt.subplots(figsize=(6,6))
#ax1.set_title('Lengua materna')
xx = range(len(count))

ax1.bar(xx, count, width=0.8, align='center')
ax1.set_xticks(xx)
ax1.set_xticklabels(all_languages)

plt.show()

Tarea 1

RelintBot1

In [143]:
# Extrear variable
rb1_correct_answers = list(rb1_data['t1_correct_answers'])
In [144]:
# Obtener frecuencias  
values = [0, 1, 2, 3, 4, 5]
rb1_ni = list(map(lambda i: rb1_correct_answers.count(i), values))
rb1_fi = list(map(lambda i: i / sum(rb1_ni) * 100, rb1_ni))

d = {'F. absoluta': rb1_ni, 'F. relativa': rb1_fi }
print("\n -- RelintBot1 - Respuestas correctas en la Tarea 1 --")
pd.DataFrame(data=d)
 -- RelintBot1 - Respuestas correctas en la Tarea 1 --
Out[144]:
F. absoluta F. relativa
0 0 0.000000
1 0 0.000000
2 0 0.000000
3 6 54.545455
4 1 9.090909
5 4 36.363636
In [145]:
print("Número de respuestas correctas")
print("Media = {:.4f}".format(sum(rb1_correct_answers)/len(rb1_correct_answers)))
print("Mediana = {}".format(np.median(np.array(rb1_correct_answers))))
Número de respuestas correctas
Media = 3.8182
Mediana = 3.0

RelintBot2

In [146]:
# Extrear variable
rb2_correct_answers = list(rb2_data['t1_correct_answers'])
In [147]:
# Obtener frecuencias  
values = [0, 1, 2, 3, 4, 5]
rb2_ni = list(map(lambda i: rb2_correct_answers.count(i), values))
rb2_fi = list(map(lambda i: i / sum(rb2_ni) * 100, rb2_ni))

d = {'F. absoluta': rb2_ni, 'F. relativa': rb2_fi }
print("\n -- RelintBot2 - Respuestas correctas en la Tarea 1 --")
pd.DataFrame(data=d)
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-147-cbcb80f746cb> in <module>
      2 values = [0, 1, 2, 3, 4, 5]
      3 rb2_ni = list(map(lambda i: rb2_correct_answers.count(i), values))
----> 4 rb2_fi = list(map(lambda i: i / sum(rb2_ni) * 100, rb2_ni))
      5 
      6 d = {'F. absoluta': rb2_ni, 'F. relativa': rb2_fi }

<ipython-input-147-cbcb80f746cb> in <lambda>(i)
      2 values = [0, 1, 2, 3, 4, 5]
      3 rb2_ni = list(map(lambda i: rb2_correct_answers.count(i), values))
----> 4 rb2_fi = list(map(lambda i: i / sum(rb2_ni) * 100, rb2_ni))
      5 
      6 d = {'F. absoluta': rb2_ni, 'F. relativa': rb2_fi }

ZeroDivisionError: division by zero
In [ ]:
print("Número de respuestas correctas")
print("Media = {:.4f}".format(sum(rb2_correct_answers)/len(rb2_correct_answers)))
print("Mediana = {}".format(np.median(np.array(rb2_correct_answers))))

Tarea 2

RelintBot1

In [ ]:
# Extraer variables de la tarea 2 
rb1_t2_completed = list(rb1_data['t2_completed'])
rb1_t2_msgs = list(rb1_data['t2_messages'])
rb1_t2_chars = list(rb1_data['t2_chars'])
In [ ]:
# Determinar el número medio de mensajes cuando la tarea fue completada 
rb1_t2_avg_msgs = np.average(np.array(list(filter(lambda m: str(m) != 'nan', rb1_t2_msgs))))                                    

# Determinar el número medio de carácteres por mensaje cuando la tarea fue completada
rb1_t2_avg_chars = np.average(np.array(list(filter(lambda m: str(m) != 'nan', rb1_t2_chars))))
In [ ]:
print("Usuarios que completaron la tarea = {:.2f}%".format(rb1_t2_completed.count("Sí") / len(rb1_t2_completed)* 100))
print("Número medio de mensajes = {:.2f}".format(rb1_t2_avg_msgs))
print("Número medio de carácteres por mensaje = {:.2f}".format(rb1_t2_avg_chars))

RelintBot2

In [ ]:
# Extraer variables de la tarea 2 
rb2_t2_completed = list(rb2_data['t2_completed'])
rb2_t2_msgs = list(rb2_data['t2_messages'])
rb2_t2_chars = list(rb2_data['t2_chars'])
In [ ]:
# Determinar el número medio de mensajes cuando la tarea fue completada 
rb2_t2_avg_msgs = np.average(np.array(list(filter(lambda m: str(m) != 'nan', rb2_t2_msgs))))                                    

# Determinar el número medio de carácteres por mensaje cuando la tarea fue completada
rb2_t2_avg_chars = np.average(np.array(list(filter(lambda m: str(m) != 'nan', rb2_t2_chars))))
In [ ]:
print("Usuarios que completaron la tarea = {:.2f}%".format(rb2_t2_completed.count("Sí") / len(rb2_t2_completed)* 100))
print("Número medio de mensajes = {:.2f}".format(rb2_t2_avg_msgs))
print("Número medio de carácteres por mensaje = {:.2f}".format(rb2_t2_avg_chars))

Tarea 3

RelintBot1

In [ ]:
# Extraer variables de la tarea 3
rb1_t3_completed = list(rb1_data['t3_completed'])
rb1_t3_msgs = list(rb1_data['t3_messages'])
rb1_t3_chars = list(rb1_data['t3_chars'])
In [ ]:
# Determinar el número medio de mensajes cuando la tarea fue completada 
rb1_t3_avg_msgs = np.average(np.array(list(filter(lambda m: str(m) != 'nan', rb1_t3_msgs))))                                    

# Determinar el número medio de carácteres por mensaje cuando la tarea fue completada
rb1_t3_avg_chars = np.average(np.array(list(filter(lambda m: str(m) != 'nan', rb1_t3_chars))))
In [ ]:
print("Usuarios que completaron la tarea = {:.2f}%".format(rb1_t3_completed.count("Sí") / len(rb1_t3_completed)* 100))
print("Número medio de mensajes = {:.2f}".format(rb1_t3_avg_msgs))
print("Número medio de carácteres por mensaje = {:.2f}".format(rb1_t3_avg_chars))

RelintBot2

In [ ]:
# Extraer variables de la tarea 3
rb2_t3_completed = list(rb2_data['t3_completed'])
rb2_t3_msgs = list(rb2_data['t3_messages'])
rb2_t3_chars = list(rb2_data['t3_chars'])
In [ ]:
# Determinar el número medio de mensajes cuando la tarea fue completada 
rb2_t3_avg_msgs = np.average(np.array(list(filter(lambda m: str(m) != 'nan', rb2_t3_msgs))))                                    

# Determinar el número medio de carácteres por mensaje cuando la tarea fue completada
rb2_t3_avg_chars = np.average(np.array(list(filter(lambda m: str(m) != 'nan', rb2_t3_chars))))
In [ ]:
print("Usuarios que completaron la tarea = {:.2f}%".format(rb2_t3_completed.count("Sí") / len(rb2_t3_completed)* 100))
print("Número medio de mensajes = {:.2f}".format(rb2_t3_avg_msgs))
print("Número medio de carácteres por mensaje = {:.2f}".format(rb2_t3_avg_chars))

Usabilidad - System Usability Scale

Para obtener la puntuación SUS es necesario:

  • Preguntas impares: restar 1 a la respuesta del usuario.
  • Preguntas pares: restar la respuesta del usuario a 5.

Esto hace que todos los valores estén entre 0 y 4 (siendo 4 el mejor valor, el valor que indica una mayor usabilidad). Una vez transformadas, se deben sumar las respuestas de cada usuario y multiplicarlas por 2.5 para que los valores finales estén entre 0 y 100.

In [ ]:
sus_raw = data.filter(regex='sus_\d{1,2}', axis=1)
sus_raw
In [ ]:
# Escalar las respuestas al intervalo [0, 4]
sus_14 = np.array(sus_raw)

for i in range(sus_14.shape[0]):
    for j in range(sus_14.shape[1]):
        if (j+1) % 2 == 0:
            sus_14[i][j] = 5 - sus_14[i][j]
        else:
            sus_14[i][j] -= 1
In [ ]:
# Sumar las puntuaciones de cada usuario y multiplicarlas por 2.5
sus_scores = np.sum(sus_14, axis=1)
sus_scores = 2.5 * sus_scores
data['sus_score'] = sus_scores
sus_scores

RelintBot1

In [ ]:
rb1_data = data[data['prototype']=='RelintBot1']
rb1_sus_scores = rb1_data['sus_score']
print("Media SUS = {:.2f}".format(np.average(rb1_sus_scores)))

RelintBot2

In [ ]:
rb2_data = data[data['prototype']=='RelintBot2']
rb2_sus_scores = rb2_data['sus_score']
print("Media SUS = {:.2f}".format(np.average(rb2_sus_scores)))