2017-10-02 1 views
0

Ich benutze Python 3.6 und Pandas 0.20.3.Verstehen des Variablenbereichs und Änderungen in Python

Ich bin mir sicher, dass dies irgendwo angesprochen werden muss, aber ich kann es nicht finden. Ich ändere einen Datenrahmen innerhalb einer Funktion, indem ich Spalten hinzufüge; dann stelle ich den Datenrahmen auf die ursprünglichen Spalten wieder her. Ich gebe den Datenrahmen nicht zurück. Die hinzugefügten Spalten bleiben erhalten. Ich könnte verstehen, wenn ich Spalten innerhalb der Funktion hinzufügen, und sie sind nicht permanent und die Aktualisierung des Datenrahmens funktioniert nicht. Ich würde auch verstehen, wenn das Hinzufügen von Spalten den Datenrahmen verändert und das Zuweisen des Datenrahmens ebenfalls blockiert. Hier ist der Code:

import numpy as np 
import pandas as pd 
df = pd.DataFrame(np.random.randn(10, 5)) 
df 

, die jetzt

0    1   2    3  4 
0 0.406779 -0.481733 -1.187696 -0.210456 -0.608194 
1 0.732978 -0.079787 -0.051720 1.097441 0.089850 
2 1.859737 -1.422845 -1.148805 0.254504 1.207134 
3 0.074400 -1.352875 -1.341630 -1.371050 0.005505 
4 -0.102024 -0.905506 -0.165681 2.424180 0.761963 
5 0.400507 -0.069214 0.228971 -0.079805 -1.059972 
6 1.284812 0.843705 -0.885566 1.087703 -1.006714 
7 0.135243 0.055807 -1.217794 0.018104 -1.571214 
8 -0.524320 -0.201561 1.535369 -0.840925 0.215584 
9 -0.495721 0.284237 0.235668 -1.412262 -0.002418 

gibt, erstelle ich eine Funktion:

def mess_around(df): 
    cols = df.columns 
    df['extra']='hi' 
    df = df[cols] 

dann führen Sie es und Display Datenrahmen:

mess_around(df) 
df 

was gibt:

 0   1    2   3   4  extra 
0 0.406779 -0.481733 -1.187696 -0.210456 -0.608194 hi 
1 0.732978 -0.079787 -0.051720 1.097441 0.089850 hi 
2 1.859737 -1.422845 -1.148805 0.254504 1.207134 hi 
3 0.074400 -1.352875 -1.341630 -1.371050 0.005505 hi 
4 -0.102024 -0.905506 -0.165681 2.424180 0.761963 hi 
5 0.400507 -0.069214 0.228971 -0.079805 -1.059972 hi 
6 1.284812 0.843705 -0.885566 1.087703 -1.006714 hi 
7 0.135243 0.055807 -1.217794 0.018104 -1.571214 hi 
8 -0.524320 -0.201561 1.535369 -0.840925 0.215584 hi 
9 -0.495721 0.284237 0.235668 -1.412262 -0.002418 hi 

Ich weiß, dass ich das Problem durch Rückkehr ts lösen kann. Also kann ich das Problem beheben. Ich möchte verstehen, wo ich falsch liege. Ich vermute, dass der Umfang der Variablen ts innerhalb der Funktion liegt; Es wird ein Zeiger gegeben, aber das ändert sich nicht wegen des Umfangs. Die Spaltenzuordnung verwendet jedoch den übergebenen Zeiger und wirkt sich daher direkt auf den Datenrahmen aus. Ist das korrekt?

EDIT: Für diejenigen, die den Datenrahmen an Ort und Stelle adressieren möchten, habe ich hinzugefügt:

for c in ts.columns: 
    if c not in cols: 
     del ts[c] 

ich vermute ich, wenn ich den neuen Datenrahmen zurück, dann wird es eine potenziell große Datenrahmen sein das muss mit der Garbage Collection behandelt werden.

+0

Das ist ein guter Vorschlag ist aber in diesem Fall die Daten keine Rolle spielt. – kdragger

+1

Mein schlechter, Kommentar wurde geschrieben, bevor ich die vollständige Frage gelesen habe: p –

Antwort

1

Um zu verstehen, was passiert, sollten Sie kennen den Unterschied zwischen Weitergabe an Funktionen von Wert-Attribute im Vergleich zu ihnen durch Verweis übergeben:


Sie übergeben eine Variable df auf Ihre Funktion messing_around. Die Funktion ändert das Original Datenfeld direkt durch Hinzufügen einer Spalte.

Diese nachfolgende Codezeile scheint für Verwirrung die Ursache zu sein hier:

df = df[cols] 

Was hier passiert, ist, dass die Variable df ursprünglich einen Verweis auf Ihre Datenrahmen gehalten. Die Neuzuweisung führt jedoch dazu, dass die Variable auf ein anderes Objekt zeigt - Ihr ursprünglicher Datenrahmen wird nicht geändert.

Hier ist ein einfacheres Beispiel:

def foo(l): 
    l.insert(0, np.nan) # original modified 
    l = [4, 5, 6]   # reassignment - no change to the original, 
          # but the variable l points to something different 

lst = [1, 2, 3]  
foo(lst) 

print(lst) 
[nan, 1, 2, 3]   # notice here that the insert modifies the original, 
          # but not the reassignment 
+1

Schönes Beispiel. Super klar (zumindest für mich). Tyvm. – kdragger