Python: Simulazione esame 1

Proviamo a simulare insieme una prova d’esame! in particolare stiamo simulando l’esame del 24 7 2020

TESTO

Scrivere un programma che

  1. prenda in ingresso:
    1. un file con annotazioni di score di artefatti in ecografie polmonari, fatte da più medici diversi.
    2. due indici di medici di cui confrontare le annotazioni
  2. per ogni coppia di score s i , s j stampi il numero di volte in cui il primo medico ha annotato un’ecografica come s i ed il secondo come s j (anche quando s i = s j )
  3. stampi il numero totale di volte in cui i due medici sono stati d’accordo, ed il numero di volte in cui sono stati in disaccordo

ESMPIO File in input

video_scores.csv:

Video       Score M1        Score M2        Score M3        Score M4        Score M5        Score M6
1   2       1       2       3       3       2
2   1       2       1       1       1       2
3   3       3       3       3       3       1
4   3       3       3       3       3       3

ESMPIO DI OUTPUT

python agreement.py:

Inserire nome file: video_scores.csv
Indice primo medico: 0
Indice secondo medico: 4
M0  M4  Count
2   3   8
1   1   5
3   3   5
0   0   11
0   1   6
Totale accordo: 28
Totale disaccordo: 32

SUGGERIMENTI

Si possono implementare 5 funzioni separate:

  1. una che legga il file dati e restituisca una lista di liste di score (una per ogni video)
  2. una che data la lista di liste ed un indice, restituisca la lista di score associati al medico con quell’indice
  3. una che data la lista di liste e due indici, restituisca un dizionario che per ogni coppia di score (s i , s j ) contiene il numero di volte in cui il primo medico ha annotato con s i e il secondo con s j
  4. una che dato il dizonario (e gli indici dei medici per l’intestazione) stampi i conteggi delle varie coppie di score e calcoli e stampi i totali di accordo e disaccordo
  5. una (o un main) che realizzi il programma richiesto usando le funzioni di cui sopra

Soluzione

LEGGETE E RI LEGGETE la consegna per capire se è chiara

iniziamo seguendo i suggerimenti:

suggerimento 1
  1. una che legga il file dati e restituisca una lista di liste di score (una per ogni video)

SEMPLICE lo abbiamo sempre fatto:

def load_file(filename):   #definisco la funzione

    file = open(filename,"r") #apro il file in modalità read
    righe = file.readlines()  #leggo le tighe
    res = []                  #creo una variabile contenente il risultato

    for i in righe[1:]:       # itero sulle righe saltando la prima
                              # perche è un intestazione
        res.append(i.split()[1:])   # splitto la riga, e prendo tutti gli elementi
                                    # eccetto il primo, perche è il numero del video
    return(res)

E’ corretto il codice che abbiamo scritto fino ad ora? non lo so, ma posso verificarlo:

prova = load_file(filename)
print(prova)

si, funziona!

suggerimento 2
  1. una che data la lista di liste ed un indice, restituisca la lista di score associati al medico con quell’indice

mmmm, che cosa ci sta chiedendo? ci chiede di creare una funzione che prenda in input la lista di liste (il file che abbiamo appena caricato con load_file), e un indice (riferito ad un medico), ci restituisca una lista contenente gli score che ha dato il medico. Quindi, se come indice abbiamo inserito 1, allora il la nostra funzione deve restituire la lista [2,1,3,3,…]

SEMPLICE:

def get_score(table,index):
    scores = []
    for row in table:               #itero sulla ogni riga della tabella
        scores.append(row[index])   #mi salvo solo i valori in posizione index
    return(scores)

E’ corretto il codice che abbiamo scritto fino ad ora? non lo so, ma posso verificarlo:

prova = load_file(filename)
scores = get_score(prova,index)
print(scores)

si, funziona!

suggerimento 3
  1. una che data la lista di liste e due indici, restituisca un dizionario che per ogni coppia di score (s i , s j ) contiene il numero di volte in cui il primo medico ha annotato con s i e il secondo con s j

mmmm, che cosa ci sta chiedendo? ci chiede di creare una funzione che prenda in input la lista di liste (il file che abbiamo appena caricato con load_file), e due indici (riferiti a due medici), ci restituisca un dizionario. Il dizionario deve aver come chiave la coppia degli score data dai medici, e come valore il totale delle volte in cui si è verificata questa situazione. Esempio, supponiamo che le liste degli scores dei medici m1 e m2 siano le seguenti:

Score M1 = [2,1,3,3]
Score M2 = [1,2,3,3]

allora il dizionario in output è il seguente:

diz = {
    (2,1): 1,
    (1,2): 1,
    (3,3): 3,
    }

Ora che abbiamo capito la consegna, scrivere il codice è easy :)

def get_agreement(table,m1,m2):
    score_m1 = get_score(table,m1)  #uso la funzione che ho fatto prima per prendere gli score del medico m1
    score_m2 = get_score(table,m2)  #uso la funzione che ho fatto prima per prendere gli score del medico m2

    diz = dict()
    for i in range(len(score_m1)):       #itero sul range della lungheza degli score i.e il numero di video

        key = (score_m1[i],score_m2[i])  # creo la chiave, che è una coppia di score (score di m1, score di m2)
        if key in diz:                   # se la chiave è già presente nel dizionario, allora incremento il suo valore
            diz[key] = diz[key] + 1
        else:                            # altrimenti (se non è presente)
            diz[key] = 1                 # aggiungo la chiave al dizionario con valore 1

    return(diz)

E’ corretto il codice che abbiamo scritto fino ad ora? non lo so, ma posso verificarlo:

prova = load_file(filename)
dizionario = get_agreement(prova,m1,m2)
print(dizionario)

si, funziona!

suggerimento 4

  1. una che dato il dizonario (e gli indici dei medici per l’intestazione) stampi i conteggi delle varie coppie di score e calcoli e stampi i totali di accordo e disaccordo

In sostanza qui ci sta chiedendo di stampare l’output in un formato piu leggibile (come quelle del esempio del output), e ci sta anche chiedendo di calcolare il numero di volte in cui i medici sono in accordo e quelle in cui sono in disaccordo.

semplice:

def print_agreemnt(diz,m1,m2):
    tot_agree = 0                       #inizializzo gli agree
    tot_disagree = 0                    #inizializzo i  disagree
    print("M%d\tM%d\tCount" %(m1,m2))   #stampo un intestazione
    for i,j in diz.keys():              #itero sulle chiavi del dizionario
        print(i,"\t",j,"\t",diz[(i,j)]) #stampo score di m1, score di m2, e valore
        if i == j:                      # se sono in accordo
            tot_agree = tot_agree + diz[(i,j)]  # incremento il tot_agree
        else:                                         # se non sono in accordo
            tot_disagree = tot_disagree + diz[(i,j)]  # incremento il tot_disagree

    print("Totale accordo: ",tot_agree)
    print("Totale disaccordo: ",tot_disagree)

suggerimento 5

  1. una (o un main) che realizzi il programma richiesto usando le funzioni di cui sopra

semplice ci chiede di mettere tutto insieme:

def load_file(filename):

    file = open(filename,"r")
    righe = file.readlines()
    res = []
    for i in righe[1:]:
        res.append(i.split()[1:])

    return(res)

def get_score(table,index):
    scores = []
    for row in table:
        scores.append(row[index])

    return(scores)

def get_agreement(table,m1,m2):
    score_m1 = get_score(table,m1)
    score_m2 = get_score(table,m2)

    diz = dict()
    for i in range(len(score_m1)):
        key = (score_m1[i],score_m2[i])

        if key in diz:
            diz[key] = diz[key] + 1
        else:
            diz[key] = 1

    return(diz)



def print_agreemnt(diz,m1,m2):
    tot_agree = 0
    tot_disagree = 0
    print("M%d\tM%d\tCount" %(m1,m2))
    for i,j in diz.keys():
        print(i,"\t",j,"\t",diz[(i,j)])

        if i == j:
            tot_agree = tot_agree + diz[(i,j)]
        else:
            tot_disagree = tot_disagree + diz[(i,j)]

    print("Totale accordo: ",tot_agree)
    print("Totale disaccordo: ",tot_disagree)




filename = input("Inserire nome file")
m1 = int(input("indice medico 1: "))
m2 = int(input("indice medico 2: "))


res = load_file(filename)
agreement = get_agreement(res,m1,m2)
print_agreemnt(agreement,m1,m2)