En omfattende guide til at flette og joine DataFrames i Python Pandas, der dækker strategier som inner, outer, left og right joins med eksempler for global dataanalyse.
Python Pandas Merging: Mestring af DataFrame Joining-strategier til dataanalyse
Datamanipulation er et afgørende aspekt af dataanalyse, og Pandas-biblioteket i Python tilbyder kraftfulde værktøjer til dette formål. Blandt disse værktøjer er fletning og joining af DataFrames essentielle operationer for at kombinere datasæt baseret på fælles kolonner eller indekser. Denne omfattende guide udforsker forskellige strategier for at joine DataFrames i Pandas og giver dig den viden, der skal til for effektivt at kombinere og analysere data fra forskellige kilder.
Forståelse af DataFrame Merging og Joining
Fletning og joining af DataFrames indebærer at kombinere to eller flere DataFrames til en enkelt DataFrame baseret på en fælles kolonne eller et fælles indeks. Den primære forskel mellem `merge` og `join` er, at `merge` er en funktion i Pandas-biblioteket og typisk joiner DataFrames på kolonner, mens `join` er en DataFrame-metode, der primært joiner DataFrames på indekser, selvom den også kan bruges med kolonner.
Nøglebegreber
- DataFrames: To-dimensionelle mærkede datastrukturer med kolonner af potentielt forskellige typer.
- Fælles kolonner/indekser: Kolonner eller indekser, der deler det samme navn og datatype på tværs af DataFrames, og som fungerer som grundlag for fletning/joining.
- Join-typer: Forskellige strategier til håndtering af ikke-matchede rækker under fletnings-/joining-processen, herunder inner, outer, left og right joins.
DataFrame Merging med `pd.merge()`
`pd.merge()`-funktionen er det primære værktøj til at flette DataFrames baseret på kolonner. Den tilbyder en fleksibel måde at kombinere data på baseret på en eller flere fælles kolonner.
Syntaks
pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=False, suffixes=('_x', '_y'), copy=True, indicator=False, validate=None)
Parametre
- left: Den venstre DataFrame, der skal flettes.
- right: Den højre DataFrame, der skal flettes.
- how: Typen af merge, der skal udføres ('inner', 'outer', 'left', 'right'). Standard er 'inner'.
- on: Navnet på kolonnen/kolonnerne, der skal joines på. Disse skal findes i begge DataFrames.
- left_on: Navnet på kolonnen/kolonnerne i den venstre DataFrame, der skal bruges som join-nøgler.
- right_on: Navnet på kolonnen/kolonnerne i den højre DataFrame, der skal bruges som join-nøgler.
- left_index: Hvis True, brug indekset fra den venstre DataFrame som join-nøgle(r).
- right_index: Hvis True, brug indekset fra den højre DataFrame som join-nøgle(r).
- sort: Sorter den resulterende DataFrame leksikografisk efter join-nøglerne. Standard er False.
- suffixes: En tuple af streng-suffikser, der skal anvendes på overlappende kolonnenavne. Standard er ('_x', '_y').
- copy: Hvis False, undgå at kopiere data ind i den nye DataFrame, hvor det er muligt. Standard er True.
- indicator: Hvis True, tilføjes en kolonne kaldet '_merge', der angiver kilden til hver række.
- validate: Tjekker om fletningen er af en specificeret type. "one_to_one", "one_to_many", "many_to_one", "many_to_many".
Forklaring af Join-typer
`how`-parameteren i `pd.merge()` bestemmer typen af join, der udføres. De forskellige join-typer håndterer ikke-matchede rækker på forskellige måder.
Inner Join
Et inner join returnerer kun de rækker, der har matchende værdier i begge DataFrames baseret på join-nøglerne. Rækker med ikke-matchende værdier udelades fra resultatet.
Eksempel:
Overvej to DataFrames:
import pandas as pd
# DataFrame 1: Kundeordrer
df_orders = pd.DataFrame({
'order_id': [1, 2, 3, 4, 5],
'customer_id': [101, 102, 103, 104, 105],
'product_id': [1, 2, 1, 3, 2],
'quantity': [2, 1, 3, 1, 2]
})
# DataFrame 2: Kundeinformation
df_customers = pd.DataFrame({
'customer_id': [101, 102, 103, 106],
'customer_name': ['Alice', 'Bob', 'Charlie', 'David'],
'country': ['USA', 'Canada', 'UK', 'Australia']
})
# Inner Join
df_inner = pd.merge(df_orders, df_customers, on='customer_id', how='inner')
print(df_inner)
Output:
order_id customer_id product_id quantity customer_name country
0 1 101 1 2 Alice USA
1 2 102 2 1 Bob Canada
2 3 103 1 3 Charlie UK
I dette eksempel kombinerer inner join `df_orders` og `df_customers` DataFrames baseret på `customer_id`-kolonnen. Kun kunder, der har afgivet ordrer, inkluderes i resultatet. Kunden 'David' (customer_id 106) er udeladt, fordi han ikke har nogen ordrer.
Outer Join (Full Outer Join)
Et outer join returnerer alle rækker fra begge DataFrames, inklusive ikke-matchede rækker. Hvis en række ikke har et match i den anden DataFrame, vil de tilsvarende kolonner indeholde `NaN` (Not a Number)-værdier.
Eksempel:
# Outer Join
df_outer = pd.merge(df_orders, df_customers, on='customer_id', how='outer')
print(df_outer)
Output:
order_id customer_id product_id quantity customer_name country
0 1.0 101 1.0 2.0 Alice USA
1 2.0 102 2.0 1.0 Bob Canada
2 3.0 103 1.0 3.0 Charlie UK
3 4.0 104 3.0 1.0 NaN NaN
4 5.0 105 2.0 2.0 NaN NaN
5 NaN 106 NaN NaN David Australia
Outer join inkluderer alle kunder og alle ordrer. Kunderne 104 og 105 har ordrer, men ingen kundeinformation, og kunde 106 har kundeinformation, men ingen ordrer. De manglende værdier er repræsenteret som `NaN`.
Left Join
Et left join returnerer alle rækker fra den venstre DataFrame og de matchende rækker fra den højre DataFrame. Hvis en række i den venstre DataFrame ikke har et match i den højre DataFrame, vil de tilsvarende kolonner fra den højre DataFrame indeholde `NaN`-værdier.
Eksempel:
# Left Join
df_left = pd.merge(df_orders, df_customers, on='customer_id', how='left')
print(df_left)
Output:
order_id customer_id product_id quantity customer_name country
0 1 101 1 2 Alice USA
1 2 102 2 1 Bob Canada
2 3 103 1 3 Charlie UK
3 4 104 3 1 NaN NaN
4 5 105 2 2 NaN NaN
Left join inkluderer alle ordrer fra `df_orders`. Kunderne 104 og 105 har ordrer, men ingen kundeinformation, så `customer_name`- og `country`-kolonnerne er `NaN` for disse ordrer.
Right Join
Et right join returnerer alle rækker fra den højre DataFrame og de matchende rækker fra den venstre DataFrame. Hvis en række i den højre DataFrame ikke har et match i den venstre DataFrame, vil de tilsvarende kolonner fra den venstre DataFrame indeholde `NaN`-værdier.
Eksempel:
# Right Join
df_right = pd.merge(df_orders, df_customers, on='customer_id', how='right')
print(df_right)
Output:
order_id customer_id product_id quantity customer_name country
0 1.0 101 1.0 2.0 Alice USA
1 2.0 102 2.0 1.0 Bob Canada
2 3.0 103 1.0 3.0 Charlie UK
3 NaN 106 NaN NaN David Australia
Right join inkluderer alle kunder fra `df_customers`. Kunde 106 har kundeinformation, men ingen ordrer, så `order_id`-, `product_id`- og `quantity`-kolonnerne er `NaN` for den kunde.
DataFrame Joining med `df.join()`
`df.join()`-metoden bruges primært til at joine DataFrames baseret på deres indekser. Den kan også bruges til at joine på kolonner, men det er typisk mere bekvemt at bruge `pd.merge()` til kolonnebaserede joins.
Syntaks
DataFrame.join(other, on=None, how='left', lsuffix='', rsuffix='', sort=False)
Parametre
- other: Den anden DataFrame, der skal joines.
- on: Kolonnenavn at joine på. Skal angives, hvis indekset ikke bruges som join-nøgle.
- how: Hvordan operationen med venstre og højre sæt skal håndteres. Standard er 'left'.
- lsuffix: Suffiks, der skal bruges fra venstre DataFrame til at overskrive overlappende kolonnenavne.
- rsuffix: Suffiks, der skal bruges fra højre DataFrame til at overskrive overlappende kolonnenavne.
- sort: Sorter den resulterende DataFrame leksikografisk efter join-nøglerne. Standard er False.
Joining på indeks
Når der joines på indekset, bruges `on`-parameteren ikke.
Eksempel:
# DataFrame 1: Kundeordrer med kunde-id som indeks
df_orders_index = df_orders.set_index('customer_id')
# DataFrame 2: Kundeinformation med kunde-id som indeks
df_customers_index = df_customers.set_index('customer_id')
# Join på indeks (Left Join)
df_join_index = df_orders_index.join(df_customers_index, how='left')
print(df_join_index)
Output:
order_id product_id quantity customer_name country
customer_id
101 1 1 2 Alice USA
102 2 2 1 Bob Canada
103 3 1 3 Charlie UK
104 4 3 1 NaN NaN
105 5 2 2 NaN NaN
I dette eksempel bruges `join()`-metoden til at udføre et left join på indekset (`customer_id`). Resultatet ligner et left join med `pd.merge()`, men joinet er baseret på indekset i stedet for en kolonne.
Joining på kolonne
For at joine på en kolonne med `df.join()` skal du specificere `on`-parameteren.
Eksempel:
# Joining på en kolonne
df_join_column = df_orders.join(df_customers.set_index('customer_id'), on='customer_id', how='left')
print(df_join_column)
Output:
order_id customer_id product_id quantity customer_name country
0 1 101 1 2 Alice USA
1 2 102 2 1 Bob Canada
2 3 103 1 3 Charlie UK
3 4 104 3 1 NaN NaN
4 5 105 2 2 NaN NaN
Dette eksempel demonstrerer joining af `df_orders` med `df_customers` ved hjælp af `customer_id`-kolonnen. Bemærk, at `customer_id` er sat som indeks i `df_customers`, før joinet udføres.
Håndtering af overlappende kolonner
Når man fletter eller joiner DataFrames, er det almindeligt at støde på overlappende kolonnenavne (kolonner med samme navn i begge DataFrames). Pandas tilbyder `suffixes`-parameteren i `pd.merge()` og `lsuffix`- og `rsuffix`-parametrene i `df.join()` til at håndtere disse situationer.
Brug af `suffixes` i `pd.merge()`
`suffixes`-parameteren giver dig mulighed for at specificere suffikser, der vil blive tilføjet til de overlappende kolonnenavne for at skelne dem fra hinanden.
Eksempel:
# DataFrame 1: Produktinformation
df_products1 = pd.DataFrame({
'product_id': [1, 2, 3],
'product_name': ['Product A', 'Product B', 'Product C'],
'price': [10, 20, 15]
})
# DataFrame 2: Produktinformation (med potentielt opdaterede priser)
df_products2 = pd.DataFrame({
'product_id': [1, 2, 4],
'product_name': ['Product A', 'Product B', 'Product D'],
'price': [12, 18, 25]
})
# Merge med suffikser
df_merged_suffixes = pd.merge(df_products1, df_products2, on='product_id', suffixes=('_old', '_new'))
print(df_merged_suffixes)
Output:
product_id product_name_old price_old product_name_new price_new
0 1 Product A 10 Product A 12
1 2 Product B 20 Product B 18
I dette eksempel er `product_name`- og `price`-kolonnerne til stede i begge DataFrames. `suffixes`-parameteren tilføjer suffikserne `_old` og `_new` for at skelne kolonnerne fra henholdsvis venstre og højre DataFrames.
Brug af `lsuffix` og `rsuffix` i `df.join()`
`lsuffix`- og `rsuffix`-parametrene giver lignende funktionalitet for `df.join()`. `lsuffix` tilføjes til venstre DataFrames overlappende kolonner, og `rsuffix` til højre DataFrames.
Eksempel:
# Join med lsuffix og rsuffix
df_products1_index = df_products1.set_index('product_id')
df_products2_index = df_products2.set_index('product_id')
df_joined_suffixes = df_products1_index.join(df_products2_index, lsuffix='_old', rsuffix='_new', how='outer')
print(df_joined_suffixes)
Output:
product_name_old price_old product_name_new price_new
product_id
1 Product A 10.0 Product A 12.0
2 Product B 20.0 Product B 18.0
3 Product C 15.0 NaN NaN
4 NaN NaN Product D 25.0
Praktiske eksempler og use cases
Fletning og joining af DataFrames bruges i vid udstrækning i forskellige dataanalyse-scenarier. Her er nogle praktiske eksempler:
Kombinering af salgsdata med produktinformation
En almindelig use case er at kombinere salgsdata med produktinformation. Antag, at du har en DataFrame, der indeholder salgstransaktioner, og en anden DataFrame, der indeholder produktdetaljer. Du kan flette disse DataFrames for at berige salgsdataene med produktinformation.
Eksempel:
# Salgstransaktionsdata
df_sales = pd.DataFrame({
'transaction_id': [1, 2, 3, 4, 5],
'product_id': [101, 102, 103, 101, 104],
'quantity': [2, 1, 3, 1, 2],
'sales_date': ['2023-01-15', '2023-02-20', '2023-03-10', '2023-04-05', '2023-05-01']
})
# Produktinformationsdata
df_products = pd.DataFrame({
'product_id': [101, 102, 103, 104],
'product_name': ['Laptop', 'Mouse', 'Keyboard', 'Monitor'],
'category': ['Electronics', 'Electronics', 'Electronics', 'Electronics'],
'price': [1200, 25, 75, 300]
})
# Flet salgsdata med produktinformation
df_sales_enriched = pd.merge(df_sales, df_products, on='product_id', how='left')
print(df_sales_enriched)
Output:
transaction_id product_id quantity sales_date product_name category price
0 1 101 2 2023-01-15 Laptop Electronics 1200
1 2 102 1 2023-02-20 Mouse Electronics 25
2 3 103 3 2023-03-10 Keyboard Electronics 75
3 4 101 1 2023-04-05 Laptop Electronics 1200
4 5 104 2 2023-05-01 Monitor Electronics 300
Den resulterende DataFrame `df_sales_enriched` indeholder salgstransaktionerne sammen med den tilsvarende produktinformation, hvilket giver mulighed for en mere detaljeret analyse af salgstendenser og produktpræstationer.
Kombinering af kundedata med demografisk information
En anden almindelig use case er at kombinere kundedata med demografisk information. Dette giver mulighed for at analysere kundeadfærd baseret på demografiske faktorer.
Eksempel:
# Kundedata
df_customers = pd.DataFrame({
'customer_id': [1, 2, 3, 4, 5],
'customer_name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve'],
'city': ['New York', 'London', 'Tokyo', 'Sydney', 'Berlin']
})
# Demografiske informationsdata
df_demographics = pd.DataFrame({
'city': ['New York', 'London', 'Tokyo', 'Sydney', 'Berlin'],
'population': [8419000, 8982000, 13960000, 5312000, 3769000],
'average_income': [75000, 65000, 85000, 90000, 55000]
})
# Flet kundedata med demografisk information
df_customer_demographics = pd.merge(df_customers, df_demographics, on='city', how='left')
print(df_customer_demographics)
Output:
customer_id customer_name city population average_income
0 1 Alice New York 8419000 75000
1 2 Bob London 8982000 65000
2 3 Charlie Tokyo 13960000 85000
3 4 David Sydney 5312000 90000
4 5 Eve Berlin 3769000 55000
Den resulterende DataFrame `df_customer_demographics` indeholder kundedata sammen med den demografiske information for deres respektive byer, hvilket muliggør analyse af kundeadfærd baseret på bydemografi.
Analyse af globale forsyningskædedata
Pandas merging er værdifuldt til analyse af globale forsyningskædedata, hvor information ofte er spredt over flere tabeller. For eksempel kan sammenkædning af leverandørdata, forsendelsesinformation og salgstal afsløre flaskehalse og optimere logistikken.
Eksempel:
# Leverandørdata
df_suppliers = pd.DataFrame({
'supplier_id': [1, 2, 3],
'supplier_name': ['GlobalTech', 'EuroParts', 'AsiaSource'],
'location': ['Taiwan', 'Germany', 'China']
})
# Forsendelsesdata
df_shipments = pd.DataFrame({
'shipment_id': [101, 102, 103, 104],
'supplier_id': [1, 2, 3, 1],
'destination': ['USA', 'Canada', 'Australia', 'Japan'],
'shipment_date': ['2023-01-10', '2023-02-15', '2023-03-20', '2023-04-25']
})
# Flet leverandør- og forsendelsesdata
df_supply_chain = pd.merge(df_shipments, df_suppliers, on='supplier_id', how='left')
print(df_supply_chain)
Output:
shipment_id supplier_id destination shipment_date supplier_name location
0 101 1 USA 2023-01-10 GlobalTech Taiwan
1 102 2 Canada 2023-02-15 EuroParts Germany
2 103 3 Australia 2023-03-20 AsiaSource China
3 104 1 Japan 2023-04-25 GlobalTech Taiwan
Avancerede fletningsteknikker
Fletning på flere kolonner
Du kan flette DataFrames baseret på flere kolonner ved at sende en liste af kolonnenavne til `on`-parameteren.
Eksempel:
# DataFrame 1
df1 = pd.DataFrame({
'product_id': [1, 1, 2, 2],
'color': ['red', 'blue', 'red', 'blue'],
'quantity': [10, 15, 20, 25]
})
# DataFrame 2
df2 = pd.DataFrame({
'product_id': [1, 1, 2, 2],
'color': ['red', 'blue', 'red', 'blue'],
'price': [5, 7, 8, 10]
})
# Merge på flere kolonner
df_merged_multiple = pd.merge(df1, df2, on=['product_id', 'color'], how='inner')
print(df_merged_multiple)
Output:
product_id color quantity price
0 1 red 10 5
1 1 blue 15 7
2 2 red 20 8
3 2 blue 25 10
Fletning med forskellige kolonnenavne
Hvis join-kolonnerne har forskellige navne i de to DataFrames, kan du bruge `left_on`- og `right_on`-parametrene til at specificere de kolonnenavne, der skal bruges til fletning.
Eksempel:
# DataFrame 1
df1 = pd.DataFrame({
'product_id': [1, 2, 3],
'product_name': ['Product A', 'Product B', 'Product C']
})
# DataFrame 2
df2 = pd.DataFrame({
'id': [1, 2, 4],
'price': [10, 20, 25]
})
# Merge med forskellige kolonnenavne
df_merged_different = pd.merge(df1, df2, left_on='product_id', right_on='id', how='left')
print(df_merged_different)
Output:
product_id product_name id price
0 1 Product A 1.0 10.0
1 2 Product B 2.0 20.0
2 3 Product C NaN NaN
Brug af `indicator` til fletningsanalyse
`indicator`-parameteren i `pd.merge()` tilføjer en kolonne ved navn `_merge` til den resulterende DataFrame, der angiver kilden til hver række. Dette er nyttigt for at forstå, hvilke rækker der blev matchet, og hvilke der ikke blev.
Eksempel:
# Merge med indikator
df_merged_indicator = pd.merge(df_orders, df_customers, on='customer_id', how='outer', indicator=True)
print(df_merged_indicator)
Output:
order_id customer_id product_id quantity customer_name country _merge
0 1.0 101 1.0 2.0 Alice USA both
1 2.0 102 2.0 1.0 Bob Canada both
2 3.0 103 1.0 3.0 Charlie UK both
3 4.0 104 3.0 1.0 NaN NaN left_only
4 5.0 105 2.0 2.0 NaN NaN left_only
5 NaN 106 NaN NaN David Australia right_only
`_merge`-kolonnen angiver, om rækken er fra begge DataFrames (`both`), kun den venstre DataFrame (`left_only`) eller kun den højre DataFrame (`right_only`).
Validering af fletningstyper
`validate`-parameteren sikrer, at merge-operationen stemmer overens med de forventede relationstyper mellem DataFrames (f.eks. 'one_to_one', 'one_to_many'). Dette hjælper med at forhindre datainkonsistenser og fejl.
Eksempel:
# Eksempel med en-til-en-validering
df_users = pd.DataFrame({
'user_id': [1, 2, 3],
'username': ['john_doe', 'jane_smith', 'peter_jones']
})
df_profiles = pd.DataFrame({
'user_id': [1, 2, 3],
'profile_description': ['Software Engineer', 'Data Scientist', 'Project Manager']
})
# Udfører en en-til-en-merge med validering
merged_df = pd.merge(df_users, df_profiles, on='user_id', validate='one_to_one')
print(merged_df)
Hvis fletningen overtræder den specificerede validering (f.eks. en mange-til-en-relation, når 'one_to_one' er specificeret), vil en `MergeError` blive udløst, hvilket advarer dig om potentielle dataintegritetsproblemer.
Overvejelser om ydeevne
Fletning og joining af DataFrames kan være beregningsmæssigt dyrt, især for store datasæt. Her er nogle tips til at forbedre ydeevnen:
- Brug den passende join-type: At vælge den korrekte join-type kan have en betydelig indvirkning på ydeevnen. For eksempel, hvis du kun har brug for matchende rækker, skal du bruge et inner join.
- Indekser join-kolonnerne: Indeksering af join-kolonnerne kan fremskynde fletningsprocessen.
- Brug passende datatyper: Sørg for, at join-kolonnerne har kompatible datatyper.
- Undgå unødvendige kopier: Sæt `copy=False` i `pd.merge()` og `df.join()` for at undgå at oprette unødvendige kopier af dataene.
Konklusion
Fletning og joining af DataFrames er grundlæggende operationer i dataanalyse. Ved at forstå de forskellige join-typer og -teknikker kan du effektivt kombinere og analysere data fra forskellige kilder, hvilket åbner op for værdifuld indsigt og fremmer informeret beslutningstagning. Fra at kombinere salgsdata med produktinformation til at analysere globale forsyningskæder vil mestring af disse teknikker give dig mulighed for at håndtere komplekse datamanipulationsopgaver med selvtillid. Husk at overveje ydeevnekonsekvenser, når du arbejder med store datasæt, og udnyt avancerede funktioner som `indicator`- og `validate`-parametrene for en mere robust og indsigtsfuld analyse.