Python - Summering av attribut-kombinationer

Permalänk
Medlem

Python - Summering av attribut-kombinationer

Hej allihopa!

Sitter med ett litet projekt i Python där jag tränat en ai-modell med maskinlärning att identifera ett antal objekt som rör sig i video.
Objekten kommer, utifrån dess positionering, att få till sig två olika attribut.

Object.O = (antingen A, B, C eller D)
Object.D = (antingen A, B, C eller D, men inte samma som .O)

Så, varje objekt kan således få någon av följande kombinationer;
A-B, A-C, A-D, B-A, B-C, B-D, C-A, C-B, C-D, D-A, D-B eller D-C.

Så objekten har då exempelvis;
Object.ID = 573, Object.O = A, Object.D = C (allts för id 573)
eller
Object.ID = 1034, Object.O = D, Object.D = B

Jag vill nu summera antalet för varje kombination så som
Antal A-C = 14
Antal A-D = 23 etc.

Skulle behöva er hjälp då hjärnan är lite trött.
Funderar på att sätta ihop det i någon pandas-tabell eller liknande.

Har ni några förslag på enklast sätt istället för att skapa 4x3 = 12 stycken olika if-satser?

Permalänk
Medlem

Nu kan jag inte Python...

En tvådimensionell array som lagrar summorna är väl det naturliga? En for-loop över objekten indexerar in i arrayen. Det blir ju trevligast om fälten O och D har en datatyp som är en enum, dvs A=0, B=1 osv. Då slipper du if-satserna.

C#:ish pseudokod:

Med enum:

public enum Values { A = 0, B = 1, C = 2, D = 3 } public class Object { public int ID; public Values O; public Values D; } var objects = new List<Object>() objects.Add(new Object() {ID = 573, O = Values.A, D = Values.C }); var sums = new int[4][4]; // Initierar med nollor foreach(var obj in objects) { sums[(int)obj.O][(int)obj.D]++; }

Utan enum:

foreach(var obj in objects) { sums [obj.O == "A" ? 0 : (obj.O == "B" ? 1 : (obj.O == "C" ? 2 : (obj.O == "D" ? 3)))] [obj.D == "A" ? 0 : (obj.D == "B" ? 1 : (obj.D == "C" ? 2 : (obj.D == D ? "3")))]++; }

Hämta en summa:

var sumAC = sums[(int)Values.A][(int)Values.C];

Permalänk
Medlem

Du skulle ju kunna lagra räknaren som value i en dictionary.
Förutsatt att A, B, C, D är string kan du använda eval för att bygga nycklarna.

combinations = dict() key = eval(f'{Object.O}-{Object.D}') try: combinations[key] += 1 except KeyError: combinations.update({key, 1})

Ovanstående med reservation för att min Python-kunskap är begränsad, så kan kanske finnas slarvfel.

EDIT:
Faktum är att, nu när jag tänker på det, eval är antagligen inte rätt att använda i just detta fall i.om. att den också ska exekvera uttrycket, vilket inte är önskvärt här.

Det borde räcka att helt enkelt bara bygga en textsträng enligt key = f'{Object.O}-{Object.D}'.

Tankevurpa
Permalänk
Medlem

Det senare förslaget får nog betraktas som bättre än mitt. Det är ju också relativt lätt att utöka till N dimensioner (attribut) och är ju inte heller lika knutet till att fler värden inte tillkommer.

Permalänk
Medlem

Tack för era förslag!

Fastnade för pandas av andra anledningar och om någon stöter på detta problem framöver så gjorde jag såhär:

För att räkna antalet Obj som har anordningen B-C

obj_dict = {'id': Object.ID,
'orig': Object.O,
'dest': Object.D}
obj_list.append(obj_dict)
df = pd.DataFrame(obj_list)
print(df.loc[(df['orig'] == 'B') & (df['dest' == 'C']), 'id'].nunique())