Python: Simulazione esame 2

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

TESTO

Scrivere un programma che

  1. prenda in ingresso un file con annotazioni di score di artefatti in ecografie polmonari, fatte da più medici diversi.
  2. calcoli per ogni video lo score con pi‘ănnotazioni (score di consenso)
  3. restituisca per ogni score il numero di video annotati con quello score di consenso

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 majority.py:

Inserire nome file: video_scores.csv
Majority score counts
2 (19) 1 (16) 0 (16) 3 (9)

SUGGERIMENTI

Si possono implementare 5 funzioni separate:

  1. una che legga il file dati e restituisca per ogni video la lista di score, ignorando eventuali valori ’NC’ (non classificabile)
  2. una che data una lista di score restituisca lo score più frequente
  3. una che data le liste di score di tutti i video, calcoli per ciascuno lo score più frequente (usando la funzione precedente) e restituisca un dizionario di conteggi degli score più frequenti
  4. una che stampi il dizionario di score e conteggi in ordine decrescente per conteggi.
  5. una (o un main) che realizzi il programma richiesto usando le funzioni di cui sottostringa_piu_lunga

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 per ogni video la lista di score, ignorando eventuali valori ’NC’ (non classificabile)

SEMPLICE lo abbiamo sempre fatto:

def load_scores(filename):
    f = open(filename)
    all_scores = []
    f.readline()
    for row in f:               # itero su ogni riga del file in input
        data = row.split()      # splitto la riga
        tmp = []                # uso un array temporaneo
        for i in data[1:]:      # per ogni numero di artefatti in data (senza l'elem in pos 0 [che è il numero video])
            if i != "NC":       # se i non è uguale a NC
                tmp.append(int(i))   # lo converto in intero e lo appendo a tmp
        all_scores.append((data[0],tmp)) #aggiungo al risultato una tupla, contenente in pos 0 il numero del video
                                         # in pos 1 l'array di score (senza NC)

    f.close()               # chiudo il file
    return all_scores       # ritorno il risultato

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

prova = load_scores(filename)
print(prova)

si, funziona!

suggerimento 2
  1. una che data una lista di score restituisca lo score più frequente

mmmm, che cosa ci sta chiedendo? data una lista di scores di un determinato video, resituisce lo score piu frequente. Es data la lista:

Video 1 = [2,1,3,3,1,1,1,1,1,1,1,1,1,1,1,1,4]

la funzione ritorna 1, perche è lo score piu frequente.

SEMPLICE:

def compute_majority_score(scores):
     counts = {}                     # inizializzo un diz
     for score in scores:            # itero su tutti gli scores
             if not score in counts:     # se score non è in count
                     counts[score] = 1           # lo aggiungo e ci mento valore 1
             else:                               # altrimenti (se score è in count)
                     counts[score] += 1          # incremento il valore di count

     max_score=-1                            # inizializzo max_score a -1
     max_count=0                             # inizializzo max_count a 0
     for (score,count) in counts.items():    # itero sul dizinario che ho creato sopra
             if count > max_count:               # se il conteggio è maggiore di max_count
                     max_score = score               # aggiorno max score
                     max_count = count               # aggiorno max count

     return max_score                        # ritorno il valore

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

file_name = "video_scores.csv"
data = load_scores(file_name)
print(data[0])
print(compute_majority_score(data[0][1]))

si, funziona!

suggerimento 3
  1. una che data le liste di score di tutti i video, calcoli per ciascuno lo score più frequente (usando la funzione precedente) e restituisca un dizionario di conteggi degli score più frequenti

mmmm, che cosa ci sta chiedendo? ci chiede di calcolare un diz, che abbia come chiave il numero di scores piu frequente di ogni video, e come valore le volte che compare. Es supponiamo di avere queste liste:

Video 1 = [2,1,3,3,1,1,1,1,1,1,1,1,1,1,1,1,4]
Video 2 = [2,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4]
Video 3 = [2,1,3,3,1,1,1,2,2,2,2,2,2,2,2,2,2]
Video 4 = [2,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3]

Lo score piu frequente è:

score piu freq di video 1 = 1
score piu freq di video 2 = 3
score piu freq di video 3 = 2
score piu freq di video 4 = 3

il dizionario in output è il seguente:

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

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

def compute_majority_counts(all_scores):
    majority_counts = {}
    for (video,scores) in all_scores:
        majority_score = compute_majority_score(scores)
        if not majority_score in majority_counts:
            majority_counts[majority_score] = 1
        else:
            majority_counts[majority_score] += 1
    return majority_counts

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

filename = "video_scores.csv"
all_scores = load_scores(filename)
majority_counts = compute_majority_counts(all_scores)
print(majority_counts)

si, funziona!

suggerimento 4

  1. una che stampi il dizionario di score e conteggi in ordine decrescente per conteggi.

semplice:

def print_majority_counts(majority_counts):
    score_list = [(count,score) for (score,count) in majority_counts.items()]
    score_list.sort(reverse=True)
    print("Majority score counts")
    print("\t".join(["%d (%d)" %(score,count) for (count,score) in score_list]))

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_scores(filename):
    f = open(filename)
    all_scores = []
    f.readline()
    for row in f:
        data = row.split()
        all_scores.append((data[0],[int(i) for i in data[1:] if i != 'NC']))
    f.close()
    return all_scores





def compute_majority_score(scores):
    counts = {}
    for score in scores:
        if not score in counts:
            counts[score] = 1
        else:
            counts[score] += 1

    max_score=-1
    max_count=0
    for (score,count) in counts.items():
        if count > max_count:
            max_score = score
            max_count = count

    return max_score

def compute_majority_counts(all_scores):
    majority_counts = {}
    for (video,scores) in all_scores:
        majority_score = compute_majority_score(scores)
        if not majority_score in majority_counts:
            majority_counts[majority_score] = 1
        else:
            majority_counts[majority_score] += 1
    return majority_counts

def print_majority_counts(majority_counts):
    score_list = [(count,score) for (score,count) in majority_counts.items()]
    score_list.sort(reverse=True)
    print("Majority score counts")
    print("\t".join(["%d (%d)" %(score,count) for (count,score) in score_list]))


filename = input("Inserire nome file: ")
all_scores = load_scores(filename)
majority_counts = compute_majority_counts(all_scores)
print_majority_counts(majority_counts)