数据框的 pandas 函数的包装器,它从文件中读取 csv 作为数据框 - df 未定义错误
Wrapper for pandas function of a dataframe, which reads a csv from file as the dataframe - df not defined error
我经常编写在数据帧上运行的函数,并带有额外的参数。 我想编写一个通用函数,我可以围绕这类函数进行包装,它将加载一个 .csv 文件作为数据帧,然后在函数中使用该数据帧。 我'我希望在某些情况下也可以选择将输出另存为另一个 .csv 文件,从而为函数提供一个文件位置来保存 .csv。
我遇到的问题是这不完全是装饰器函数,因为它包含额外的参数,即文件位置(用于加载 .csv,有时用于保存文件)。但是 我也不想为我想用 执行此操作的每个函数单独编写此函数(在这种情况下,我只是将包含函数的所有参数传递给包装函数).
我目前的尝试如下。我在 jupyter 笔记本中 运行 这个,所以它只是将 .csv 保存在主目录中并从那里加载它。
import pandas as pd
a=[1,2,3,4]
b=[5,3,7,2]
testdf=pd.DataFrame(list(zip(a,b)),columns=['A','B'])
file_in_location='test.csv'
testdf.to_csv(file_in_location)
def open_file_and_run_wrapper(func,file_in_location,file_out_location='',save_output=False,delimiter=','):
'''
Function that opens a file as a dataframe and runs it through the given function
'''
if save_output==True:
if file_out_location=='':
# raise exception
print('error: must have file output location')
df=pd.read_csv(file_in_location,delimiter=delimiter)
if save_output==True:
df.to_csv(file_out_location,delimiter=delimiter)
return func(df=df,*args,**kwargs)
def df_function(df,add_colname,value):
df[add_colname]=value
return df
open_file_and_run_wrapper(
df_function(df,'C',4),
file_in_location,
)
这个returns下面的错误:
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-3-d174cd4d8bbc> in <module>
29
30 open_file_and_run_wrapper(
---> 31 df_function(df,'C',4),
32 file_in_location,
33 )
NameError: name 'df' is not defined
这并不奇怪,因为当我开始 运行 这个函数时数据框还没有定义。但是,它将由包装函数定义。 如何创建允许附加参数的通用 wrapper/decorator 函数?
以下是编写(和调用)包装器的方法:
# notice the additional *args and **kwargs
def open_file_and_run_wrapper(func, file_in_location,
*args,
file_out_location='',
save_output=False,
delimiter=',', **kwargs):
'''
Function that opens a file as a dataframe and runs it through the given function
'''
if save_output==True:
if file_out_location=='':
# raise exception
print('error: must have file output location')
df=pd.read_csv(file_in_location,delimiter=delimiter)
if save_output==True:
df.to_csv(file_out_location,delimiter=delimiter)
# note how we pass the additional parameters
# in `df_function` `df` is not a keyword argument
# we call it as such
return func(df,*args,**kwargs)
def df_function(df,add_colname,value):
df[add_colname]=value
return df
现在,我们可以使用附加参数作为关键字参数来调用包装器
open_file_and_run_wrapper(
df_function,
file_in_location,
add_colname='C', value=4
)
或者我们也可以使用位置参数调用,但那样可读性会差一些
open_file_and_run_wrapper(
df_function,
file_in_location,
'C', 4 # positional arguments here
)
输出:
Unnamed: 0 A B C
0 0 1 5 4
1 1 2 3 4
2 2 3 7 4
3 3 4 2 4
您可以这样处理,将函数作为对象传递,然后将位置参数和关键字参数作为类似列表和类似字典的方式传递。它看起来像这样:
def open_file_and_run_wrapper(
func,
file_in_location,
func_args=[],
func_kwargs={},
file_out_location=None,
delimiter=",",
):
"""
Function that opens a file as a dataframe and runs it through the given function
"""
df = pd.read_csv(file_in_location, delimiter=delimiter)
processed_df = func(df, *func_args, **func_kwargs)
if file_out_location is not None:
processed_df.to_csv(file_out_location, delimiter=delimiter)
return processed_df
def df_function(df, add_colname, value):
df[add_colname] = value
return df
open_file_and_run_wrapper(
df_function, file_in_location, func_args=["C"], func_kwargs={"value": 5}
)
我已经对您的代码进行了一些更改,希望我没有更改您的预期。
func_args
接受列表或元组(实际上是任何序列),然后作为位置参数传递给函数
func_kwargs
接受类似字典的参数并作为关键字参数传递给函数
- 删除
save_output
以检查file_out_location
是否存在以保存函数的输出(如果没有提供file_out_location
,则不会将输出保存为文件)。
- 将调用移至
to_csv
以保存新创建的数据帧,而不是保存从文件中读取的相同数据帧
你要的是对象,不是函数
class DataWrapper:
def run(self, df):
raise NotImplementedError
def open_and_run(self, file_in_location, delimiter=','):
df = pd.read_csv(file_in_location, delimiter=delimiter)
return self.run(df)
def open_run_and_save(self, file_in_location, file_out_location, delimiter=','):
df_result = self.open_and_run(file_in_location, delimiter)
df_result.to_csv(file_out_location, delimiter=delimiter)
您的包装函数将在 运行 方法中实现,参数将在初始化程序中传递
class AddConstantColumnWrapper(DataWrapper):
def __init__(self, colname, value):
super().__init__()
self.colname = colname
self.value = value
def run(self, df):
df[self.colname] = self.value
return df
然后您可以调用该对象来执行您需要的操作
wrapper = AddConstantColumnWrapper('C',4)
df_result = wrapper.open_and_run(file_in_location)
将参数字典作为参数传递通常表明需要面向对象
我经常编写在数据帧上运行的函数,并带有额外的参数。 我想编写一个通用函数,我可以围绕这类函数进行包装,它将加载一个 .csv 文件作为数据帧,然后在函数中使用该数据帧。 我'我希望在某些情况下也可以选择将输出另存为另一个 .csv 文件,从而为函数提供一个文件位置来保存 .csv。
我遇到的问题是这不完全是装饰器函数,因为它包含额外的参数,即文件位置(用于加载 .csv,有时用于保存文件)。但是 我也不想为我想用 执行此操作的每个函数单独编写此函数(在这种情况下,我只是将包含函数的所有参数传递给包装函数).
我目前的尝试如下。我在 jupyter 笔记本中 运行 这个,所以它只是将 .csv 保存在主目录中并从那里加载它。
import pandas as pd
a=[1,2,3,4]
b=[5,3,7,2]
testdf=pd.DataFrame(list(zip(a,b)),columns=['A','B'])
file_in_location='test.csv'
testdf.to_csv(file_in_location)
def open_file_and_run_wrapper(func,file_in_location,file_out_location='',save_output=False,delimiter=','):
'''
Function that opens a file as a dataframe and runs it through the given function
'''
if save_output==True:
if file_out_location=='':
# raise exception
print('error: must have file output location')
df=pd.read_csv(file_in_location,delimiter=delimiter)
if save_output==True:
df.to_csv(file_out_location,delimiter=delimiter)
return func(df=df,*args,**kwargs)
def df_function(df,add_colname,value):
df[add_colname]=value
return df
open_file_and_run_wrapper(
df_function(df,'C',4),
file_in_location,
)
这个returns下面的错误:
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-3-d174cd4d8bbc> in <module>
29
30 open_file_and_run_wrapper(
---> 31 df_function(df,'C',4),
32 file_in_location,
33 )
NameError: name 'df' is not defined
这并不奇怪,因为当我开始 运行 这个函数时数据框还没有定义。但是,它将由包装函数定义。 如何创建允许附加参数的通用 wrapper/decorator 函数?
以下是编写(和调用)包装器的方法:
# notice the additional *args and **kwargs
def open_file_and_run_wrapper(func, file_in_location,
*args,
file_out_location='',
save_output=False,
delimiter=',', **kwargs):
'''
Function that opens a file as a dataframe and runs it through the given function
'''
if save_output==True:
if file_out_location=='':
# raise exception
print('error: must have file output location')
df=pd.read_csv(file_in_location,delimiter=delimiter)
if save_output==True:
df.to_csv(file_out_location,delimiter=delimiter)
# note how we pass the additional parameters
# in `df_function` `df` is not a keyword argument
# we call it as such
return func(df,*args,**kwargs)
def df_function(df,add_colname,value):
df[add_colname]=value
return df
现在,我们可以使用附加参数作为关键字参数来调用包装器
open_file_and_run_wrapper(
df_function,
file_in_location,
add_colname='C', value=4
)
或者我们也可以使用位置参数调用,但那样可读性会差一些
open_file_and_run_wrapper(
df_function,
file_in_location,
'C', 4 # positional arguments here
)
输出:
Unnamed: 0 A B C
0 0 1 5 4
1 1 2 3 4
2 2 3 7 4
3 3 4 2 4
您可以这样处理,将函数作为对象传递,然后将位置参数和关键字参数作为类似列表和类似字典的方式传递。它看起来像这样:
def open_file_and_run_wrapper(
func,
file_in_location,
func_args=[],
func_kwargs={},
file_out_location=None,
delimiter=",",
):
"""
Function that opens a file as a dataframe and runs it through the given function
"""
df = pd.read_csv(file_in_location, delimiter=delimiter)
processed_df = func(df, *func_args, **func_kwargs)
if file_out_location is not None:
processed_df.to_csv(file_out_location, delimiter=delimiter)
return processed_df
def df_function(df, add_colname, value):
df[add_colname] = value
return df
open_file_and_run_wrapper(
df_function, file_in_location, func_args=["C"], func_kwargs={"value": 5}
)
我已经对您的代码进行了一些更改,希望我没有更改您的预期。
func_args
接受列表或元组(实际上是任何序列),然后作为位置参数传递给函数func_kwargs
接受类似字典的参数并作为关键字参数传递给函数- 删除
save_output
以检查file_out_location
是否存在以保存函数的输出(如果没有提供file_out_location
,则不会将输出保存为文件)。 - 将调用移至
to_csv
以保存新创建的数据帧,而不是保存从文件中读取的相同数据帧
你要的是对象,不是函数
class DataWrapper:
def run(self, df):
raise NotImplementedError
def open_and_run(self, file_in_location, delimiter=','):
df = pd.read_csv(file_in_location, delimiter=delimiter)
return self.run(df)
def open_run_and_save(self, file_in_location, file_out_location, delimiter=','):
df_result = self.open_and_run(file_in_location, delimiter)
df_result.to_csv(file_out_location, delimiter=delimiter)
您的包装函数将在 运行 方法中实现,参数将在初始化程序中传递
class AddConstantColumnWrapper(DataWrapper):
def __init__(self, colname, value):
super().__init__()
self.colname = colname
self.value = value
def run(self, df):
df[self.colname] = self.value
return df
然后您可以调用该对象来执行您需要的操作
wrapper = AddConstantColumnWrapper('C',4)
df_result = wrapper.open_and_run(file_in_location)
将参数字典作为参数传递通常表明需要面向对象