Moodle'i logide analüüs¶

Autor: Nora Anete Müller¶

Eeltöötlus¶

In [1]:
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams["font.family"] = 'serif'
plt.rcParams['font.size'] = 12
import numpy as np
from numpy import mean
from numpy import std
from numpy import cov
from scipy.stats import pearsonr
from scipy.stats import spearmanr
import matplotlib.patches as mpatches
from scipy import stats
In [2]:
# Logide fail
logs = pd.read_csv('logs.csv')
In [3]:
# Eemaldatakse nende kasutajate logid, keda ei uurita
logs.drop(logs.index[logs['Kasutaja täisnimi'] == 'Nora Anete Müller'], inplace=True)
logs.drop(logs.index[logs['Kasutaja täisnimi'] == 'Tauno Palts'], inplace=True)
logs.drop(logs.index[logs['Kasutaja täisnimi'] == 'Moodle admin'], inplace=True)
logs.drop(logs.index[logs['Kasutaja täisnimi'] == '-'], inplace=True)
logs.drop(logs.index[logs['Kasutaja täisnimi'] == 'xxx xxx'], inplace=True)
logs.drop(logs.index[logs['Kasutaja täisnimi'] == 'xx xxxx'], inplace=True)
logs.drop(logs.index[logs['Kasutaja täisnimi'] == 'xxx xx'], inplace=True)
In [4]:
# hinne_vs_logid.csv on autori koostatud fail
hin_log = pd.read_csv("Hinded_logid.csv")
In [5]:
# Nimede asendamine logide failis -> nimetäht + m/f
asendamine = {}
for i in logs['Kasutaja täisnimi'].unique():
    nimi = i.split()
    eesnimi = nimi[0]
    perenimi = nimi[1]
    for index, row in hin_log.iterrows():
        if (eesnimi == row['Eesnimi'] and perenimi == row['Perenimi']):
            if (row['Sugu'] == 'f'):
                uusNimi = eesnimi[0] + 'f'
                k = 1
                while uusNimi in asendamine.values() and k < len(eesnimi):
                    uusNimi = eesnimi[k] + 'f'
                    k += 1
                if uusNimi not in asendamine.values():
                    asendamine[i] = uusNimi
                else:
                    k = 1
                    uusNimi = perenimi[0] + 'f'
                    while uusNimi in asendamine.values() and k < len(perenimi):
                        uusNimi = perenimi[k] + 'f'
                        k += 1
                    asendamine[i] = uusNimi
            elif (row['Sugu'] == 'm'):
                uusNimi = eesnimi[0] + 'm'
                k = 1
                while uusNimi in asendamine.values() and k < len(eesnimi):
                    uusNimi = eesnimi[k] + 'm'
                    k += 1
                if uusNimi not in asendamine.values():
                    asendamine[i] = uusNimi
                else:
                    k = 1
                    uusNimi = perenimi[0] + 'm'
                    while uusNimi in asendamine.values() and k < len(perenimi):
                        uusNimi = perenimi[k] + 'm'
                        k += 1
                    asendamine[i] = uusNimi
                    
logs['Kasutaja täisnimi'].replace(asendamine, inplace=True)
In [6]:
# Nimede asendamine failis 'hinned_vs_logid.csv'
hin_log.insert(0, 'Nimi', '')
nimed = []
for index, row in hin_log.iterrows():
    nimi = row['Eesnimi'] + ' ' + row['Perenimi']
    # Kui osaleja on teinud 0 logi
    if nimi not in asendamine:
        kood = '-'
    else:
        kood = asendamine[nimi]
    nimed.append(kood)

hin_log['Nimi'] = nimed
hin_log.drop('Eesnimi', axis=1, inplace=True)
hin_log.drop('Perenimi', axis=1, inplace=True)

Seos logide arvu ja lõpphinde vahel¶

In [7]:
x1 = []
y1 = []

x2 = []
y2 = []

for index, row in hin_log.iterrows():
    if (hin_log['Kursuse lõpphinne'].iloc[index] == 'arvestatud'):
        x1.append(hin_log['Hinne (Punktid)'].iloc[index])
        y1.append(hin_log['Logide arv'].iloc[index])
    else:
        x2.append(hin_log['Hinne (Punktid)'].iloc[index])
        y2.append(hin_log['Logide arv'].iloc[index])

plt.scatter(x1, y1, c='green', label='arvestatud')
plt.scatter(x2, y2, c='red', label='mitte arvestatud')
plt.legend()
plt.xlabel('Punktid')
plt.ylabel('Logide arv')
plt.savefig('Diagrammid/LogideArv_punktid.png', format='png', dpi=100)

Korrelatsioonanalüüs¶

In [8]:
logid = hin_log['Logide arv'].tolist()
punktid = hin_log['Hinne (Punktid)'].tolist()
# Mean and standard deviation
print('logid: mean=%.3f stdv=%.3f' % (mean(logid), std(logid)))
print('punktid: mean=%.3f stdv=%.3f' % (mean(punktid), std(punktid)))
logid: mean=303.979 stdv=170.578
punktid: mean=31.260 stdv=13.536
In [9]:
# calculate covariance matrix
covariance = cov(logid, punktid)
print(covariance)
[[29715.85062057  1769.28213652]
 [ 1769.28213652   187.12754876]]
In [10]:
# caluclate Pearson's correlation
corr, _ = pearsonr(logid, punktid)
print('Pearsons correaltion: %.3f' % corr)
Pearsons correaltion: 0.750

positiivne korrelatsioon => 0.75¶

T-test¶

In [11]:
stats.ttest_ind(logid, punktid)
Out[11]:
Ttest_indResult(statistic=10.926432683324903, pvalue=2.0088847999402385e-18)

p-väärtus < 0.01¶

Millistel päevadel on osalejad kõige aktiivsemad?¶

In [12]:
# Kuupäeva veeru lisamine andmetesse
logs.insert(1, 'Kuupäev', '')
logs = logs.reset_index(drop=True)

kuupäevad = []
for index, row in logs.iterrows():
    if index == len(logs):
        break
    else:
        kuupäev = row['Aeg'][0:10]
        if kuupäev[-1] == ' ':
            kuupäev = kuupäev.replace(' ','')
            kuupäev = '0' + kuupäev
            row['Aeg'] = '0' + row['Aeg']
        kuupäevad.append(kuupäev)
logs['Kuupäev'] = kuupäevad
In [13]:
def tagastaKp(el):
    return el['Kuupäev']

def sortKp(data):
    
    oktoober = []
    november = []
    detsember = []
    jaanuar = []
    
    # Kuupäevade sort kuu järgi
    for index, row in data.iterrows():
        if (row['Kuupäev'][3:5] == '10'):
            oktoober.append(row)
        elif (row['Kuupäev'][3:5] == '11'):
            november.append(row)
        elif (row['Kuupäev'][3:5] == '12'):
            detsember.append(row)
        elif (row['Kuupäev'][3:5] == '01'):
            jaanuar.append(row)
            
    # Kuupäevade sort päeva järgi
    oktoober = sorted(oktoober, key=lambda x: tagastaKp(x))
    november = sorted(november, key=lambda x: tagastaKp(x))
    detsember = sorted(detsember, key=lambda x: tagastaKp(x))
    jaanuar = sorted(jaanuar, key=lambda x: tagastaKp(x))
    
    values = oktoober + november + detsember + jaanuar
    return values

def newDf(values):
    df = pd.DataFrame(data = values, columns = logs.columns)
    return df
In [14]:
# Logide sort kuupäevade kaupa
newLogs = newDf(sortKp(logs))
In [15]:
# Logide arv erinevatel kuupäevadel
kp = newLogs['Kuupäev'].unique()
valueCounts = []
for el in kp:
    count = 0
    for index, row in newLogs.iterrows():
        if row['Kuupäev'] == el:
            count += 1
    valueCounts.append([el[:5], count])
In [16]:
# Novembri kuupäevad
kursus = []
for i in valueCounts:
    if (i[0][3:5] == '11'):
        kursus.append(i)
In [17]:
fig = plt.figure(figsize=(15,5))
ax = fig.add_subplot(111)
ax.plot([i[0] for i in kursus], [i[1] for i in kursus])
ax.set_xlabel('Kuupäevad')
ax.xaxis.label.set_size(12)
ax.set_ylabel('Logide arv')
ax.yaxis.label.set_size(12)
ax.set_xticks(['01.11','03.11','05.11','07.11','09.11','11.11','13.11','15.11','17.11','19.11','21.11','23.11','25.11',
              '27.11','29.11'])
fig.savefig('Diagrammid/LogideArv_Kuupäev.png', format='png', dpi=100)
In [18]:
# Lisanädalate kuupäevad
muu = []
for i in valueCounts:
    if (i[0][3:5] == '12'):
        muu.append(i)
In [19]:
fig = plt.figure(figsize=(15,5))
ax = fig.add_subplot(111)
ax.plot([i[0] for i in muu], [i[1] for i in muu])
ax.set_xlabel('Kuupäevad')
ax.xaxis.label.set_size(12)
ax.set_ylabel('Logide arv')
ax.yaxis.label.set_size(12)
fig.savefig('Diagrammid/LogideArv_Kuupäev_vol2.png', format='png', dpi=100)

Millistel kellaaegadel on osalejad kõige aktiivsemad?¶

In [20]:
# Kellaaja veeru lisamine andmetesse
newLogs.insert(2, 'Kellaaeg', '')

# Lisatakse ainult tunni osa kellaajast ehk '09:44:44' tuleb veergu kujul '09'
kellaajad = []
for index, row in newLogs.iterrows():
    kellaajad.append(row['Aeg'][11:13])
        
newLogs['Kellaaeg'] = kellaajad
In [21]:
# Logide arv erinevatel kellaaegadel
kl = newLogs['Kellaaeg'].unique()
valueCounts = []
for el in kl:
    count = 0
    for index, row in newLogs.iterrows():
        if row['Kellaaeg'] == el:
            count += 1
    valueCounts.append([el, count])
In [22]:
def takeTime(el):
    return el[0]
valueCounts.sort(key=takeTime)

fig = plt.figure(figsize=(10,5))
ax = fig.add_subplot(111)
ax.plot([i[0] for i in valueCounts], [i[1] for i in valueCounts])
ax.set_xlabel('Kellaajad')
ax.xaxis.label.set_size(12)
ax.set_ylabel('Logide arv')
ax.yaxis.label.set_size(12)
fig.savefig('Diagrammid/LogideArv_Kellaaeg.png', format='png', dpi=100)

Millistel nädalatel olid (arvestatud) osalejad aktiivsed?¶

In [23]:
# Nädala veeru lisamine andmetesse
newLogs.insert(3, 'Nädal', '')
nadal1 = ['01.11.2021', '02.11.2021', '03.11.2021', '04.11.2021', '05.11.2021', '06.11.2021', '07.11.2021']
nadal2 = ['08.11.2021', '09.11.2021', '10.11.2021', '11.11.2021', '12.11.2021', '13.11.2021', '14.11.2021']
nadal3 = ['15.11.2021', '16.11.2021', '17.11.2021', '18.11.2021', '18.11.2021', '19.11.2021', '20.11.2021', '21.11.2021']
nadal4 = ['22.11.2021', '23.11.2021', '24.11.2021', '25.11.2021', '26.11.2021', '27.11.2021', '28.11.2021']

nadalad = []
for index, row in newLogs.iterrows():
    if row['Kuupäev'] in nadal1:
        nadalad.append('1. nädal')
    elif row['Kuupäev'] in nadal2:
        nadalad.append('2. nädal')
    elif row['Kuupäev'] in nadal3:
        nadalad.append('3. nädal')
    elif row['Kuupäev'] in nadal4:
        nadalad.append('4. nädal')
    else:
        nadalad.append('muu')
            
newLogs['Nädal'] = nadalad
In [24]:
# Osalejate logid, kes said lõpphinde arvestatud
arvestatud = hin_log.loc[hin_log['Kursuse lõpphinne'] == 'arvestatud']
arvestatud = arvestatud['Nimi'].tolist()

arvestatud_logs = newLogs[newLogs['Kasutaja täisnimi'].isin(arvestatud)]

Logide koguarv nädalates¶

In [25]:
x = ['1. nädal', '2. nädal', '3. nädal', '4. nädal', 'muu']
y = [arvestatud_logs['Nädal'].value_counts().sort_index()[0], arvestatud_logs['Nädal'].value_counts().sort_index()[1],
    arvestatud_logs['Nädal'].value_counts().sort_index()[2], arvestatud_logs['Nädal'].value_counts().sort_index()[3], 
    arvestatud_logs['Nädal'].value_counts().sort_index()[4]]

fig = plt.figure(figsize=(15,10))
ax = fig.add_subplot(111)
ax.bar(x, y)
ax.bar_label(ax.containers[0])
ax.set_ylabel('Logide arv')
ax.yaxis.label.set_size(12)
In [26]:
kasutajad = []
nimed = []
for i, row in arvestatud_logs.iterrows():
    if (row['Nädal'] == '1. nädal'):
        nimed.append(row['Kasutaja täisnimi'])
kasutajad.append(len(list(set(nimed))))

nimed = []
for i, row in arvestatud_logs.iterrows():
    if (row['Nädal'] == '2. nädal'):
        nimed.append(row['Kasutaja täisnimi'])
kasutajad.append(len(list(set(nimed))))

nimed = []
for i, row in arvestatud_logs.iterrows():
    if (row['Nädal'] == '3. nädal'):
        nimed.append(row['Kasutaja täisnimi'])
kasutajad.append(len(list(set(nimed))))

nimed = []
for i, row in arvestatud_logs.iterrows():
    if (row['Nädal'] == '4. nädal'):
        nimed.append(row['Kasutaja täisnimi'])
kasutajad.append(len(list(set(nimed))))

nimed = []
for i, row in arvestatud_logs.iterrows():
    if (row['Nädal'] == 'muu'):
        nimed.append(row['Kasutaja täisnimi'])
kasutajad.append(len(list(set(nimed))))

Unikaalsete kasutajate arv nädalates¶

In [27]:
x = ['1. nädal', '2. nädal', '3. nädal', '4. nädal', 'muu']

fig = plt.figure(figsize=(15,8))
ax = fig.add_subplot(111)
ax.bar(x, kasutajad)
ax.bar_label(ax.containers[0])
ax.set_ylabel('Kasutajate arv')
ax.yaxis.label.set_size(12)
In [28]:
# Keskmise logide arvu leidmine
new_y = []
for i in y:
    for k in kasutajad:
        new_y.append(i / k)
        break

Keskmine logide arv nädalates¶

In [29]:
x = ['1. nädal', '2. nädal', '3. nädal', '4. nädal', 'muu']
fig = plt.figure(figsize=(15,8))
plt.bar(x, new_y)

labels = []
for i in new_y:
    labels.append(str(round(i,2)).replace('.', ','))
    
for i in range(len(x)):
    plt.text(i, new_y[i]+0.02, labels[i], ha='center', va='bottom', fontsize=12)
    
plt.ylabel('Keskmine logide arv', fontsize=12)
fig.savefig('Diagrammid/LogideArv_Nädalad_keskmine.png', format='png', dpi=100)

Automaatkontrollidega ülesannete analüüs¶

In [30]:
vpl = ['VPL harjutus: Kontrollülesanne 1.1. Kuldnokk (tähtaeg: 7. november)',
    'VPL harjutus: Kontrollülesanne 2.1. Valikulause (tähtaeg: 14. november)',
    'VPL harjutus: Kontrollülesanne 2.2. Sõned (tähtaeg: 14. november)',
    'VPL harjutus: Kontrollülesanne 3.1. Tsükkel (tähtaeg 21. november)',
    'VPL harjutus: Kontrollülesanne 3.2. Regulaaravaldis (tähtaeg: 21. november)',
    'VPL harjutus: Kontrollülesanne 4.1. Funktsioonid (tähtaeg: 28. november)',
    'VPL harjutus: Lisaülesanne. Küpsisetort (ei ole kohustuslik)',
    'VPL harjutus: Lisaülesanne: Nädalapalk (ei ole kohustuslik)',
    'VPL harjutus: Lisaülesanne: Eurod ja sendid (ei ole kohustuslik)',
    'VPL harjutus: Lisaülesanne: Supp (ei ole kohustuslik)',
    'VPL harjutus: Lisaülesanne: Autonumber (ei ole kohustuslik)',
    'VPL harjutus: Lisaülesanne: Pere sissetulek 2017 (ei ole kohustuslik)']
In [31]:
lisa = ['Lisaülesanne. Küpsisetort',
    'Lisaülesanne: Nädalapalk',
    'Lisaülesanne: Eurod ja sendid',
    'Lisaülesanne: Supp',
    'Lisaülesanne: Autonumber',
    'Lisaülesanne: Pere sissetulek 2017']
In [32]:
vpl_data = newLogs.loc[newLogs['Sündmuse kontekst'].isin(vpl)]
In [33]:
# Uued nimetused ülesannetele, et oleks diagrammilt kergem lugeda
vpl_uus = [
    'Kontrollülesanne 1.1. Kuldnokk', 'Lisaülesanne. Küpsisetort',
    'Kontrollülesanne 2.2. Sõned','Kontrollülesanne 2.1. Valikulause',
    'Lisaülesanne: Eurod ja sendid','Lisaülesanne: Nädalapalk', 'Kontrollülesanne 3.1. Tsükkel',
    'Lisaülesanne: Autonumber', 'Lisaülesanne: Supp','Kontrollülesanne 3.2. Regulaaravaldis',
    'Kontrollülesanne 4.1. Funktsioonid','Lisaülesanne: Pere sissetulek 2017'
]
In [34]:
kontekst = vpl_data['Sündmuse kontekst'].unique().tolist()
for i in kontekst:
    indeks = kontekst.index(i)
    vpl_data['Sündmuse kontekst'].replace({i: vpl_uus[indeks]}, inplace=True)
C:\Users\Nora\anaconda3\lib\site-packages\pandas\core\generic.py:6619: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  return self._update_inplace(result)
In [35]:
x = []
y = []
nimi = []
kasutajad = []
tegevus = 'mod_vpl: submission uploaded'
for v in vpl_uus:
    harjutus = v
    if (harjutus not in lisa):
        x.append(harjutus)
        count = 0
        for i, row in vpl_data.iterrows():
            if (row['Sündmuse kontekst'] == harjutus and row['Sündmuse nimi'] == tegevus):
                count += 1
                nimi.append(row['Kasutaja täisnimi'])
        kasutajad.append(len(list(set(nimi))))
        y.append(count)
        nimi = []
In [36]:
x2 = []
y2 = []
nimi = []
kasutajad2 = []
tegevus = 'mod_vpl: submission uploaded'
for v in vpl_uus:
    harjutus = v
    if (harjutus in lisa):
        x2.append(harjutus)
        count = 0
        for i, row in vpl_data.iterrows():
            if (row['Sündmuse kontekst'] == harjutus and row['Sündmuse nimi'] == tegevus):
                count += 1
                nimi.append(row['Kasutaja täisnimi'])
        kasutajad2.append(len(list(set(nimi))))
        y2.append(count)
        nimi = []
In [37]:
a, b = x.index('Kontrollülesanne 2.2. Sõned'), x.index('Kontrollülesanne 2.1. Valikulause')
x[b], x[a] = x[a], x[b]
y[b], y[a] = y[a], y[b]

Üleslaadimiste koguarv¶

In [38]:
fig = plt.figure(figsize=(25,10))
ax = fig.add_subplot(111)
ax.bar(x, y)
ax.bar_label(ax.containers[0])
ax.set_ylabel('Üleslaadimiste arv')
Out[38]:
Text(0, 0.5, 'Üleslaadimiste arv')

Lisaülesannetes üleslaadimiste koguarv¶

In [39]:
fig = plt.figure(figsize=(22,8))
ax = fig.add_subplot(111)
ax.bar(x2, y2)
ax.bar_label(ax.containers[0])
ax.set_ylabel('Üleslaadimiste arv')
Out[39]:
Text(0, 0.5, 'Üleslaadimiste arv')
In [40]:
kasutajad[b], kasutajad[a] = kasutajad[a], kasutajad[b]

Kontrollülesandeid lahendanud kasutajad¶

In [41]:
fig = plt.figure(figsize=(27, 8))
ax = fig.add_subplot(111)
ax.bar(x, kasutajad)
ax.bar_label(ax.containers[0])
ax.set_ylabel('Kasutajate arv')
Out[41]:
Text(0, 0.5, 'Kasutajate arv')

Lisaülesandeid lahendanud kasutajad¶

In [42]:
fig = plt.figure(figsize=(22, 8))
ax = fig.add_subplot(111)
ax.bar(x2, kasutajad2)
ax.bar_label(ax.containers[0])
ax.set_ylabel('Kasutajate arv')
Out[42]:
Text(0, 0.5, 'Kasutajate arv')
In [43]:
# Keskmise arvutamine (kontrollülesanded)
new_y = []
for i in y:
    for k in kasutajad:
        new_y.append(i / k)
        break

# Keskmise arvutamine (lisaülesanded)
new_y2 = []
for i in y2:
    for k in kasutajad2:
        new_y2.append(i / k)
        break
In [44]:
new_y[b], new_y[a] = new_y[a], new_y[b]

Keskmine üleslaadimiste arv¶

In [45]:
fig = plt.figure(figsize=(16,8))
plt.bar(x, new_y)

labels = []
for i in new_y:
    labels.append(str(round(i,2)).replace('.', ','))
    
for i in range(len(x)):
    plt.text(i, new_y[i]+0.02, labels[i], ha='center', va='bottom')

labels = ['1.1. Kuldnokk','2.1. Valikulause','2.2. Sõned','3.1. Tsükkel','3.2. Regulaaravaldis','4.1. Funktsioonid']
plt.xticks(x, labels)
plt.xlabel('Kohustuslikud kontrollülesanded', labelpad=20)
plt.ylabel('Keskmine üleslaadimiste arv', labelpad=10)
fig.savefig('Diagrammid/VPL_keskmine.png', format='png', dpi=100)

Keskmine üleslaadimiste arv (lisaülesanded)¶

In [46]:
import locale
locale.setlocale(locale.LC_NUMERIC, "de_DE")
plt.rcParams['axes.formatter.use_locale'] = True

fig = plt.figure(figsize=(15,8))
plt.bar(x2, new_y2)

labels = []
for i in new_y2:
    labels.append(str(round(i,2)).replace('.', ','))
    
for i in range(len(x2)):
    plt.text(i, new_y2[i]+0.02, labels[i], ha='center', va='bottom', fontsize=12)
    
labels = ['Küpsisetort','Eurod ja sendid','Nädalapalk','Autonumber', 'Supp','Pere sissetulek 2017']
plt.xticks(x2, labels) 
plt.xlabel('Lisaülesanded', labelpad=10)
plt.ylabel('Keskmine üleslaadimiste arv', labelpad=10)

fig.savefig('Diagrammid/VPL_keskmine_lisa.png', format='png', dpi=100)