IDs miteinander verknüpfen

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
KrisCrow
User
Beiträge: 11
Registriert: Dienstag 10. August 2021, 13:00

Hallo miteinander,

ich muss wieder einmal IDs vergleichen (ähnlich viewtopic.php?f=30&t=52746). Nur brauche ich in diesen Fall alle "verknüpften" IDs in eine art Tabelle.
Denn später soll nur diese eine Tabelle geladen werden (z.B. als csv-Datei gespeichert) und anhand dessen Datei(-namen) oder Spalten in wieder anderen Dateien zugeordnet werden.

Hier ein Minimalbeispiel:

Code: Alles auswählen

import pandas as pd

energy_heat = {'ID_old_one': ['id01', 'id02', 'id03'], 'ID_old_two': ['id05', 'id04', 'id07'], 'apfel': [5, 13, 18]}
df_energy_heat = pd.DataFrame(data=energy_heat)
df_energy_heat

energy_sun = {'ID_old_one': ['id09', 'id04', 'id05'], 'ID_old_two': ['id03', 'id06', 'id07'], 'birne': [17, 3, 12]}
df_energy_sun = pd.DataFrame(data=energy_sun)
df_energy_sun

### ... Blackbox ...

index_energy = {'ID_new': ['id0a', 'id0b'], 'ID_old': [['id01','id05', 'id07', 'id08', 'id09'], ['id02', 'id04', 'id06']]}
df_index_energy = pd.DataFrame(data=index_energy)
df_index_energy

energy_heat = {'ID_new': ['id0a', 'id0b', 'id0a'], 'apfel': [5, 13, 18]}
df_energy_heat = pd.DataFrame(data=energy_heat)
df_energy_heat

energy_sun = {'ID_new': ['id0a', 'id0b', 'id0a'], 'birne': [17, 3, 12]}
df_energy_sun = pd.DataFrame(data=energy_sun)
df_energy_sun
Statt "Blackbox" habe ich mich mit Schleifen versucht. Da die Dateien aber durchaus 1 Mio. oder mehr Zeilen haben können, würde das Ausführen Tage dauern.
Ich hoffe die Zuordnung ist klar?

Das Ergebnis (Variable: index_energy) kann auch (programmiertechnisch: Liste, Dataframe, dic, ...) anders gestalten sein. Es muss nur klar die ID zuordenbar sein.
Es werden aus vielen verschiedenen Programmen Dateien ausgegeben, in welche "verknüpfte Werte" miteinander verglichen werden sollen.

Wie kann man die Blackbox ohne Schleifen gestallten?

Vielen Dank.
KrisCrow
User
Beiträge: 11
Registriert: Dienstag 10. August 2021, 13:00

Ich habe das jetzt ein bisschen anders gelöst, leider mit vielen Schleifen:

Dasselbe wie oben:

Code: Alles auswählen

import pandas as pd
from tqdm import tqdm

energy_heat = {'ID_old_one': ['id01', 'id02', 'id03'], 'ID_old_two': ['id05', 'id04', 'id07'], 'apfel': [5, 13, 18]}
df_energy_heat = pd.DataFrame(data=energy_heat)

energy_sun = {'ID_old_one': ['id09', 'id04', 'id05'], 'ID_old_two': ['id03', 'id06', 'id07'], 'birne': [17, 3, 12]}
df_energy_sun = pd.DataFrame(data=energy_sun)
Jetzt wird ein neues DataFrame erstellt, mit links der neuen-ID und rechts der alten-ID
Hier gibt es die neue-ID mehrfach. Das ist ja so gewollt, damit man jede alte-ID eindeutig zuordnen kann.

Code: Alles auswählen

df_index = pd.DataFrame()
df_index['ID_old_one'] = energy_heat['ID_old_one']
df_index['ID_old_two'] = energy_heat['ID_old_two']

df_index2 = pd.DataFrame()
df_index2['ID_old_one'] = energy_sun['ID_old_one']
df_index2['ID_old_two'] = energy_sun['ID_old_two']

df_index5 = pd.DataFrame()
df_index5['neueID'] = ()
df_index5['Erste'] = df_index['ID_old_one'].append(df_index2['ID_old_one'], ignore_index=True)
df_index5['Zweite'] = df_index['ID_old_two'].append(df_index2['ID_old_two'], ignore_index=True)

nbr_ids = len(df_index5)
df_newID = pd.DataFrame(columns=['newID', 'oldID'])

start_nbr = 0
stop_nbr = nbr_ids
pbar_nbr = 100/(stop_nbr - start_nbr)


with tqdm(total=100) as pbar:
    
    # Alle alten IDs einmal durchgehen
    for n in range(start_nbr, stop_nbr, 1):
        
        # wenn bei den alten IDs noch keine neue vergeben ist
        #if df_index5['newID'][n].isnull().values.any():
        if str(df_index5['neueID'][n]) == 'nan':
            newID_no = 'nID_' + str(n)
            #newID_no = n
            df_index5['neueID'][n] = newID_no
        
        # wenn bei den alten IDs schon eine neue ID vermerkt ist
        else:
            newID_no = df_index5['neueID'][n]

        # nach selben Werten wie linke oder rechte alte-ID suchen und dort die neue ID vermerken
        if not str(df_index5['Erste'][n]) == '':
            # Falls die Zahl schon einmal ein einem anderen Bezug gesetzt wurde die Zahl neu definieren
            if df_index5['Erste'][n] in df_newID.values:
                index_temp = df_newID[df_newID['oldID'] == df_index5['Erste'][n]].index.tolist()
                if index_temp:
                    index_temp = df_newID[df_newID['newID'] == df_newID['newID'][index_temp[0]]].index.tolist()
                    for x in range(0, len(index_temp), 1):
                        df_newID["newID"][index_temp[x]] = newID_no
            else:
                # in neuer Tabelle die neue-ID und die rechte und dann linke alte-ID eintragen
                df_temp = pd.DataFrame({"newID":[newID_no], "oldID":[df_index5['Erste'][n]]})
                df_newID = df_newID.append(df_temp, ignore_index=True)  
                
            index_temp = df_index5[df_index5['Erste'] == df_index5['Erste'][n]].index.tolist()
            if index_temp:
                for x in range(0, len(index_temp), 1):
                    df_index5["neueID"][index_temp[x]] = newID_no

            index_temp = df_index5[df_index5['Erste'] == df_index5['Zweite'][n]].index.tolist()
            if index_temp:
                for x in range(0, len(index_temp), 1):
                    df_index5["neueID"][index_temp[x]] = newID_no

        if not str(df_index5['Zweite'][n]) == '':
            # Falls die Zahl schon einmal ein einem anderen Bezug gesetzt wurde die Zahl neu definieren
            if df_index5['Zweite'][n] in df_newID.values:
                index_temp = df_newID[df_newID['oldID'] == df_index5['Zweite'][n]].index.tolist()
                if index_temp:
                    index_temp = df_newID[df_newID['newID'] == df_newID['newID'][index_temp[0]]].index.tolist()
                    for x in range(0, len(index_temp), 1):
                        df_newID["newID"][index_temp[x]] = newID_no
            else:
                # in neuer Tabelle die neue-ID und die rechte und dann linke alte-ID eintragen
                df_temp = pd.DataFrame({"newID":[newID_no], "oldID":[df_index5['Zweite'][n]]})
                df_newID = df_newID.append(df_temp, ignore_index=True)   
                
            index_temp = df_index5[df_index5['Zweite'] == df_index5['Erste'][n]].index.tolist()
            if index_temp:
                for x in range(0, len(index_temp), 1):
                    df_index5["neueID"][index_temp[x]] = newID_no

            index_temp = df_index5[df_index5['Zweite'] == df_index5['Zweite'][n]].index.tolist()
            if index_temp:
                for x in range(0, len(index_temp), 1):
                    df_index5["neueID"][index_temp[x]] = newID_no

        pbar.update(pbar_nbr)

Ausgabe ist dann das neue Dataframe:

Code: Alles auswählen

df_newID

	newID 	oldID
0 	nID_2 	id01
1 	nID_2 	id05
2 	nID_1 	id02
3 	nID_1 	id04
4 	nID_2 	id03
5 	nID_2 	id07
6 	nID_2 	id09
7 	nID_1 	id06
  • Was haltet ihr davon?
  • Masterfrage: wie bekomme ich das ohne (oder mit weniger) Schleifen hin?
Bonus Frage: Wie bekomme ich diese Warnung weg? Ich konnte die Ursache nicht eingrenzen.

Code: Alles auswählen

A value is trying to be set on a copy of a slice from a DataFrame
Vielen Dank.
Antworten