2015-12-08 3 views
1

Je suis nouveau à python et je suis en train de passer un argument (dataframe) à une valeur de fonction et le changement de l'argument (dataframe) en lisant un fichier Excel. (Supposons que j'ai importé tous les fichiers nécessaires)Le passage d'un dataframe python à un objet et modifier la trame de données

J'ai remarqué que python ne passe pas l'argument par référence ici et je finis par ne pas avoir l'image de données initialisée/modifiée.

I lecture qui passe par python-référence d'objet et non par la valeur ou de référence. Cependant, je n'ai pas besoin de changer le même dataframe.

La sortie est: class 'pandas.core.frame.DataFrame'>

from pandas import DataFrame as df 
class Data: 
    x = df 

    @staticmethod 
    def import_File(df_name , file): 
     df_name = pd.io.excel.read_excel(file.replace('"',''), sheetname='Sheet1', header=0, skiprows=None, skip_footer=0, index_col=None, parse_cols=None, parse_dates=True, date_parser=True, na_values=None, thousands=None, convert_float=True, has_index_names=None, converters=None, engine=None) 


def inputdata(): 
    Data.import_File(Data.x,r"C:\Users\Data\try.xlsx") 
    print(Data.x) 
+0

Veuillez nous indiquer comment nous pouvons vous aider à résoudre cette question. Sinon, si vous trouvez que l'une des réponses répond à votre question, veuillez l'accepter. Merci! – imp9

Répondre

2

Dans votre code df est un objet de classe. Pour créer un cadre de données vide, vous devez l'instancier. Instantiating classes en Python utilise la notation de fonction. De plus, nous n'avons pas besoin de passer les paramètres par défaut lorsque nous lisons le fichier Excel. Cela aidera le code à paraître plus propre.
En outre, nous n'avons pas besoin de transmettre les paramètres par défaut lorsque nous lisons le fichier Excel. Cela aidera le code à paraître plus propre.

from pandas import DataFrame as df 
class Data: 
    x = df() 

    @staticmethod 
    def import_File(df_name, file): 
     df_name = pd.io.excel.read_excel(file.replace('"',''), sheetname='Sheet1') 

Lorsque vous passez Data.x-import_File(), df_name se référera au même objet que Data.x, qui dans ce cas est un vide dataframe. Cependant, lorsque vous attribuez à pd.io.excel.read_excel(file)df_name alors la connexion entre df_name et le vide dataframe est cassé, et df_name se réfère maintenant à la trame de données Excel. Data.x n'a subi aucun changement pendant ce processus, donc il est toujours connecté à l'objet de trame de données vide.

Une façon plus simple de voir cela avec les chaînes:

x = 'red' 
df_name = x 

Nous pouvons briser l'objet entre chaîne « rouge » connexion df_name et forment un nouveau avec l'objet « excel`.

df_name = 'excel' 
print(x) 
'red' 

Cependant, il y a une solution simple pour Data.x pour retourner la trame de données Excel.

from pandas import DataFrame as df 
class Data: 
    x = df() 

    @staticmethod 
    def import_File(file): 
     Data.x = pd.io.excel.read_excel(file.replace('"',''), sheetname='Sheet1') 

def inputdata(): 
    Data.import_File(r"C:\Users\Data\try.xlsx") 
    print(Data.x) 

Cependant, je ne recommande pas d'utiliser staticmethods, et vous devez inclure un constructeur dans votre classe comme l'autre réponse a recommandé.

4

Vous semblez faire beaucoup de choses à la dure. Je vais essayer de le simplifier tout en respectant les modes d'utilisation standard.

# Whatever imports you need 
import pandas as pd 


# Static variables and methods should generally be avoided. 
# Change class and variable names to whatever is more suitable. 
# Names should be meaningful when possible. 
class MyData: 

    # Load data in constructor. Could easily do this in another method. 
    def __init__(self, filename): 
     self.data = pd.io.excel.read_excel(filename, sheetname='Sheet1') 


def inputData(): 
    # In my experience, forward slashes work just fine on Windows. 
    # Create new MyData object using constructor 
    x = MyData('C:/Users/Data/try.xlsx') 

    # Access member variable from object 
    print(x.data) 

est ici la version où il charge dans une méthode plutôt que le constructeur.

import pandas as pd 


class MyData: 

    # Constructor 
    def __init__(self): 
     # Whatever setup you need 
     self.data = None 
     self.loaded = False 

    # Method with optional argument 
    def loadFile(self, filename, sheetname='Sheet1') 
     self.data = pd.io.excel.read_excel(filename, sheetname=sheetname) 
     self.loaded = True 


def inputData(): 
    x = MyData() 
    x.loadFile('C:/Users/Data/try.xlsx') 
    print(x.data) 

    # load some other data, using sheetname 'Sheet2' instead of default 
    y = MyData() 
    y.loadFile('C:/Users/Data/tryagain.xlsx', 'Sheet2') 
    # can also pass arguments by name in any order like this: 
    # y.loadFile(sheetname='Sheet2', filename='C:/Users/Data/tryagain.xlsx') 
    print(y.data) 

    # x and y both still exist with different data. 
    # calling x.loadFile() again with a different path will overwrite its data. 

La raison pour laquelle il ne sauve pas dans votre code d'origine est parce que l'attribution de valeurs aux noms d'argument ne change jamais la variable d'origine en Python.Qu'est-ce que vous pouvez faire est quelque chose comme ceci:

# Continuing from the last code block 

def loadDefault(data): 
    data.loadFile('C:/Users/Data/try.xlsx') 

def testReference(): 
    x = MyData() 
    loadDefault(x) 
    # x.data now has been loaded 
    print(x.data) 


# Another example 

def setIndex0(variable, value): 
    variable[0] = value 

def testSetIndex0(): 
    v = ['hello', 'world'] 
    setIndex0(v, 'Good morning') 
    # v[0] now equals 'Good morning' 
    print(v[0]) 

Mais vous ne pouvez pas faire ceci:

def setString(variable, value): 
    # The only thing this changes is the value of variable inside this function. 
    variable = value 

def testSetString(): 
    v = 'Start' 
    setString(v, 'Finish') 
    # v is still 'Start' 
    print(v) 

Si vous voulez être en mesure de préciser l'emplacement pour stocker une valeur en utilisant un nom, vous pourrait utiliser une structure de données avec des index/clés. Les dictionnaires vous permettent d'accéder et de stocker des valeurs à l'aide d'une clé.

import pandas as pd 


class MyData: 

    # Constructor 
    def __init__(self): 
     # make data a dictionary 
     self.data = {} 

    # Method with optional argument 
    def loadFile(self, storename, filename, sheetname='Sheet1') 
     self.data[storename] = pd.io.excel.read_excel(filename, sheetname=sheetname) 

    # Access method 
    def getData(self, name): 
     return self.data[name] 


def inputData(): 
    x = MyData() 
    x.loadFile('name1', 'C:/Users/Data/try.xlsx') 
    x.loadFile('name2', 'C:/Users/Data/tryagain.xlsx', 'Sheet2') 

    # access Sheet1 
    print(x.getData('name1')) 

    # access Sheet2 
    print(x.getData('name2')) 

Si vous voulez vraiment que la fonction soit statique, vous n'avez pas du tout besoin de créer une nouvelle classe. La principale raison de créer une classe est de l'utiliser comme une structure réutilisable pour contenir des données avec des méthodes spécifiques à ces données.

import pandas as pd 

# wrap read_excel to make it easier to use 
def loadFile(filename, sheetname='Sheet1'): 
    return pd.io.excel.read_excel(filename, sheetname=sheetname) 

def inputData(): 
    x = loadFile('C:/Users/Data/try.xlsx') 
    print(x) 

    # the above is exactly the same as 
    x = pd.io.excel.read_excel('C:/Users/Data/try.xlsx', sheetname='Sheet1') 
    print(x) 
+0

Merci pour vos réponses. Cependant, j'ai pensé à une situation où plusieurs attributs de données existent dans une classe. disons x, y, z et je voudrais avoir une méthode simple pour instancier chacun avec une méthode en obtenant leurs noms et en important le fichier. Imaginons que nous ayons plusieurs dataframes à charger dans un objet de classe. J'ai utilisé static car le chargement d'un fichier excel ne semble pas spécifique à un objet de classe. –

+1

J'ai ajouté quelques autres exemples, j'espère qu'ils traitent de la façon dont vous auriez une quantité variable de données dans un objet et comment vous pourriez utiliser une fonction au lieu d'une classe. – Darcinon

+0

Merci, très utile. –