Pandas & NumPy Academy · Les

Prestatievoordelen van gesorteerde indexen

Sorteer een MultiIndex met sort_index(), meet de prestaties van slices met timeit en gebruik is_monotonic_increasing als controle.

Les 4 van 413 stappen

Prestatievoordelen van gesorteerde indexen is een gratis Pandas & NumPy Academy-les op CoddyKit. Dit is les 4 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Pandas & NumPy Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Pandas & NumPy Academy bevat in totaal 4 lessen.

Waarom het sorteren van indices belangrijk is voor prestaties

Met een gesorteerde index kan Pandas binair zoeken (O(log n)) gebruiken in plaats van een volledige lineaire scan (O(n)) bij het opzoeken van labelbereiken. Voor een DataFrame met één miljoen rijen vindt binair zoeken het doelbereik in ongeveer 20 vergelijkingen, tegenover maximaal één miljoen vergelijkingen bij een lineaire scan. Daardoor zijn segmentbewerkingen op gesorteerde MultiIndex-objecten vele ordes van grootte sneller dan op ongesorteerde objecten — en het verschil wordt cruciaal in productiegegevensverwerkingspijplijnen die miljoenen rijen verwerken.

import pandas as pd
import numpy as np

np.random.seed(42)
# Create a large DataFrame with a MultiIndex
countries = ['DE', 'UK', 'USA', 'FR', 'JP']
dates = pd.date_range('2020-01-01', periods=200)
mi = pd.MultiIndex.from_product([countries, dates], names=['country', 'date'])
df = pd.DataFrame({'value': np.random.randn(len(mi))}, index=mi)

print(f'DataFrame shape: {df.shape}')
print(f'Index is sorted: {df.index.is_monotonic_increasing}')

Controleren of een index gesorteerd is

Gebruik df.index.is_monotonic_increasing om te controleren of de index in oplopende volgorde is gesorteerd. Dit geeft een boolean terug. Bij een MultiIndex controleert Pandas de lexicografische sortering over alle niveaus. Controleer dit altijd voordat u segmentbewerkingen uitvoert met .loc[start:end] op een MultiIndex — een ongesorteerde index veroorzaakt afhankelijk van de Pandas-versie een UnsortedIndexError of retourneert stilzwijgend onjuiste resultaten.

import pandas as pd

# Sorted MultiIndex
tuples_sorted = [('A', 1), ('A', 2), ('B', 1), ('B', 2)]
mi_sorted = pd.MultiIndex.from_tuples(tuples_sorted)
df_sorted = pd.DataFrame({'v': [10, 20, 30, 40]}, index=mi_sorted)

# Unsorted MultiIndex
tuples_unsorted = [('B', 2), ('A', 1), ('B', 1), ('A', 2)]
mi_unsorted = pd.MultiIndex.from_tuples(tuples_unsorted)
df_unsorted = pd.DataFrame({'v': [10, 20, 30, 40]}, index=mi_unsorted)

print('Sorted index is_monotonic_increasing:', df_sorted.index.is_monotonic_increasing)
print('Unsorted index is_monotonic_increasing:', df_unsorted.index.is_monotonic_increasing)

Sorteren met sort_index()

df.sort_index() retourneert een nieuw DataFrame waarvan de rijen in oplopende volgorde volgens het indexlabel zijn gesorteerd. Gebruik ascending=False voor aflopende volgorde. Bij een MultiIndex is de sortering lexicografisch: eerst wordt op het buitenste niveau gesorteerd en vervolgens op de binnenste niveaus binnen elke buitenste groep. Sorteer altijd na elke bewerking die de volgorde van de index kan verstoren — zoals pd.concat, filteren of nieuwe rijen toevoegen.

import pandas as pd
import numpy as np

np.random.seed(0)
countries = ['USA', 'UK', 'DE']
years = [2021, 2022, 2023]
mi = pd.MultiIndex.from_product([countries, years], names=['country', 'year'])
df = pd.DataFrame({'gdp': np.random.randint(3000, 26000, 9)}, index=mi)

print('Before sort_index():')
print(df.head(4))

df_sorted = df.sort_index()
print('\nAfter sort_index():')
print(df_sorted.head(4))
print('Is sorted:', df_sorted.index.is_monotonic_increasing)

Opzoektijd meten met timeit

De Python-module timeit meet hoe lang het duurt om een instructie uit te voeren door deze vele malen uit te voeren en het gemiddelde te berekenen. Gebruik de module om het opzoeken in gesorteerde en ongesorteerde indices te benchmarken. In IPython/Jupyter biedt de magic %timeit dezelfde functionaliteit met overzichtelijkere uitvoer. Benchmarken is de enige betrouwbare manier om te bevestigen dat een prestatieoptimalisatie daadwerkelijk heeft geholpen — neem nooit aan dat een wijziging sneller is zonder dit te meten.

import pandas as pd
import numpy as np
import timeit

np.random.seed(0)
N = 500000
idx = np.random.choice(['A','B','C','D','E'], N)
df_unsorted = pd.DataFrame({'v': np.random.randn(N)}, index=idx)
df_sorted = df_unsorted.sort_index()

# Time label lookup: sorted vs unsorted
t_unsorted = timeit.timeit(lambda: df_unsorted.loc['C'], number=100)
t_sorted = timeit.timeit(lambda: df_sorted.loc['C'], number=100)

print(f'Unsorted lookup (100 runs): {t_unsorted:.3f}s')
print(f'Sorted lookup  (100 runs): {t_sorted:.3f}s')
print(f'Speedup: {t_unsorted/t_sorted:.1f}x')

PerformanceWarning bij een ongesorteerde MultiIndex

Pandas geeft een PerformanceWarning wanneer u een MultiIndex segmenteert die niet lexicografisch is gesorteerd: 'indexing past lexsort depth may impact performance'. Deze waarschuwing betekent dat Pandas moest terugvallen op een lineaire scan in plaats van binair zoeken. Hoewel dit in eenvoudige gevallen nog steeds correcte resultaten oplevert, kan het onjuiste resultaten retourneren wanneer u binnenste niveaus van een ongesorteerde index met meerdere niveaus segmenteert. Behandel deze waarschuwing als een fout en los de onderliggende oorzaak op door de index te sorteren.

import pandas as pd
import warnings

# Create an unsorted MultiIndex and trigger the warning
tuples = [('B', 2), ('A', 1), ('B', 1), ('A', 2)]
mi = pd.MultiIndex.from_tuples(tuples, names=['letter', 'num'])
df = pd.DataFrame({'v': [10, 20, 30, 40]}, index=mi)

print('Index sorted?', df.index.is_monotonic_increasing)

# This may trigger PerformanceWarning in some Pandas versions
with warnings.catch_warnings(record=True) as w:
    warnings.simplefilter('always')
    try:
        result = df.loc['A':'B', :]
        print('Result:', result)
        if w:
            print('Warning:', str(w[0].message))
    except Exception as e:
        print('Error (common with newer Pandas):', type(e).__name__)

Benchmarken van segmentering op gesorteerde en ongesorteerde MultiIndex-objecten

Segmentering van een gesorteerde MultiIndex is veel sneller omdat Pandas binair kan zoeken in zowel de arrays van het buitenste als het binnenste niveau. Laten we het segmenteren van een grote MultiIndex met 1 miljoen rijen benchmarken — een veelvoorkomende omvang in productieanalysepijplijnen. De gesorteerde versie vermijdt de lineaire scan en laat afhankelijk van de selectiviteit van het segment consequent snelheidswinsten van 5 tot 50 keer zien.

import pandas as pd
import numpy as np
import timeit

np.random.seed(42)
countries = ['DE', 'UK', 'USA', 'FR', 'JP']
dates = pd.date_range('2010-01-01', periods=200000)

# Sample a random subset for timing test
sample_countries = np.random.choice(countries, 100000)
sample_dates = np.random.choice(dates, 100000)

df = pd.DataFrame({
    'country': sample_countries,
    'date': sample_dates,
    'value': np.random.randn(100000)
}).set_index(['country', 'date'])

df_sorted = df.sort_index()
print('Dataset size:', len(df))
print('Sorted:', df_sorted.index.is_monotonic_increasing)

t = timeit.timeit(lambda: df_sorted.loc['USA'], number=50)
print(f'Sorted lookup (50 runs): {t:.3f}s')

sort_index met de parameter level

Bij een MultiIndex kunt u met de parameter level op een specifiek niveau sorteren in plaats van op alle niveaus: df.sort_index(level='year'). Dit is handig wanneer u de groepering op het buitenste niveau wilt behouden, maar de rijen binnen elke buitenste groep opnieuw wilt ordenen. Het argument sort_remaining=True (standaardwaarde) sorteert ook alle ongesorteerde niveaus na het opgegeven niveau, zodat de volledige lexicografische volgorde wordt gegarandeerd.

import pandas as pd
import numpy as np

countries = ['USA', 'UK']
years = [2023, 2021, 2022]  # deliberately unordered
mi = pd.MultiIndex.from_product([countries, years], names=['country', 'year'])
df = pd.DataFrame({'v': range(6)}, index=mi)

print('Before sorting by year level:')
print(df)

# Sort by the inner level (year) only
df_ysorted = df.sort_index(level='year')
print('\nAfter sort_index(level="year"):')
print(df_ysorted)

is_monotonic_increasing als bewaking van een pijplijn

Voeg in productiegegevensverwerkingspijplijnen aan het begin van elke functie die een DataFrame met een MultiIndex ontvangt en segmentering uitvoert een sorteercontrole toe. Als de index niet is gesorteerd, sorteert u deze automatisch en logt u een waarschuwing. Zo voorkomt u een stilzwijgende afname van de prestaties of onjuiste resultaten wanneer code stroomopwaarts de volgorde van het DataFrame wijzigt. Een controle aan de grens van de functie is betrouwbaarder dan aannemen dat aanroepers altijd gesorteerde gegevens doorgeven.

import pandas as pd
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

def safe_slice(df, key):
    '''Slice a MultiIndex DataFrame, sorting if necessary.'''
    if not df.index.is_monotonic_increasing:
        logger.warning('Index not sorted — sorting now. This is a performance cost.')
        df = df.sort_index()
    return df.loc[key]

# Test with an unsorted DataFrame
tuples = [('B', 2), ('A', 1), ('B', 1), ('A', 2)]
mi = pd.MultiIndex.from_tuples(tuples, names=['letter', 'num'])
df = pd.DataFrame({'v': [10, 20, 30, 40]}, index=mi)

result = safe_slice(df, 'A')
print('Slice result for A:')
print(result)

Gesorteerde index voor binair zoeken op eenvoudige indices

De prestatievoordelen van sorteren gelden ook voor reguliere indices (geen MultiIndex). Een DatetimeIndex die voor tijdreeksanalyse wordt gebruikt, voert segmentering van datumbereiken veel sneller uit wanneer deze gesorteerd is. Met een alfabetisch gesorteerde tekenreeksindex kan binair worden gezocht naar labels. Voor een grote Series met aandelenkoersen die op tijdstempels is geïndexeerd, kan het sorteren van de DatetimeIndex een segmentbewerking van 100 ms terugbrengen tot een bewerking die minder dan een milliseconde duurt.

import pandas as pd
import numpy as np
import timeit

np.random.seed(0)
# Random timestamps — unsorted
timestamps = pd.date_range('2020-01-01', periods=500000, freq='min')
shuffled = np.random.permutation(timestamps)

prices = pd.Series(np.random.randn(500000), index=shuffled)
prices_sorted = prices.sort_index()

# Time a date range slice
t_unsorted = timeit.timeit(lambda: prices['2020-06-01':'2020-06-30'], number=20)
t_sorted = timeit.timeit(lambda: prices_sorted['2020-06-01':'2020-06-30'], number=20)

print(f'Unsorted: {t_unsorted:.3f}s')
print(f'Sorted:   {t_sorted:.3f}s')
print(f'Speedup: {t_unsorted/t_sorted:.0f}x')

Geheugenkosten van sorteren

Sorteren is niet gratis — sort_index() maakt een nieuwe kopie van het DataFrame (tenzij u inplace=True gebruikt, waarmee het DataFrame ter plaatse wordt gewijzigd). Bij zeer grote DataFrames verdubbelt dit tijdelijk het maximale geheugengebruik. Een praktische strategie is om eenmalig te sorteren tijdens het laden en de gesorteerde versie gedurende de hele pijplijn te behouden, in plaats van herhaaldelijk te sorteren. Als het geheugen beperkt is, sorteert u ter plaatse met df.sort_index(inplace=True) om de tijdelijke kopie te vermijden.

import pandas as pd
import numpy as np

np.random.seed(0)
countries = ['DE', 'UK', 'USA']
years = [2021, 2022, 2023]
mi = pd.MultiIndex.from_product([countries, years], names=['country', 'year'])
df = pd.DataFrame({'v': np.random.randn(9)}, index=mi)

# Sort once at load time — best practice
df.sort_index(inplace=True)  # no temporary copy
assert df.index.is_monotonic_increasing, 'Index must be sorted!'
print('Pipeline-ready DataFrame (sorted in place):')
print(df)

Samenvatting van aanbevolen werkwijzen voor gesorteerde indices

Belangrijke regels voor indexprestaties: 1) Roep altijd sort_index() aan na elke bewerking die de index kan verstoren (concat, merge, append, filter). 2) Gebruik is_monotonic_increasing als controle in functies die de index segmenteren. 3) Sorteer tijdens het laden en behoud het gesorteerde DataFrame gedurende de hele pijplijn om herhaald sorteren te voorkomen. 4) Zorg er bij MultiIndex-DataFrames voor dat alle niveaus zijn gesorteerd, niet alleen het buitenste niveau. 5) Gebruik timeit om te controleren of sorteren in uw specifieke pijplijn daadwerkelijk de verwachte snelheidswinst oplevert.

Korte controle

Test uw begrip van de prestaties van gesorteerde indices uit deze les.

Samenvatting van de les

In deze les hebt u geleerd: is_monotonic_increasing controleert of een index gesorteerd is en of binair zoeken beschikbaar is, sort_index() sorteert ter plaatse of retourneert een gesorteerde kopie, en timeit meet de daadwerkelijke snelheidswinst om het voordeel te bevestigen. Hierna bekijken we vensterfuncties — voortschrijdende en uitbreidende statistieken voor tijdreeksen en financiële gegevens.

Gratis beginnen

Leer Python met een AI-tutor — gratis

Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.

Cursussen
30
Lessen
120

Veelgestelde vragen

Is de les “Prestatievoordelen van gesorteerde indexen” gratis?

Ja — de volledige tekst van “Prestatievoordelen van gesorteerde indexen” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus Pandas & NumPy Academy wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus Pandas & NumPy Academy bevat in totaal 4 lessen.

Wat leer ik in “Prestatievoordelen van gesorteerde indexen”?

Sorteer een MultiIndex met sort_index(), meet de prestaties van slices met timeit en gebruik is_monotonic_increasing als controle. Je oefent met Pandas & NumPy Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.

Heb ik ervaring nodig om met Pandas & NumPy Academy te beginnen?

Ervaring vooraf is niet nodig. Pandas & NumPy Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 4 van 4.

Hoe lang duurt de les “Prestatievoordelen van gesorteerde indexen”?

De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.

Kan ik code schrijven en uitvoeren in deze les over Pandas & NumPy Academy?

Ja. Elke les over Pandas & NumPy Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.

Alle lessen in deze cursus

  1. Een MultiIndex maken
  2. Gegevens uit een MultiIndex selecteren
  3. Indexuitlijning en herindexering
  4. Prestatievoordelen van gesorteerde indexen
← Terug naar Pandas & NumPy Academy