如果为空,附加到 DataFrame 的问题
Issue with appending to DataFrame if empty
我有一个在本地方法范围外初始化的数据框。我想做如下:
def outer_method():
... do outer scope stuff here
df = pd.DataFrame(columns=['A','B','C','D'])
def recursive_method(arg):
... do local stuff here
# func returns a data frame to be appended to empty data frame
results_df = func(args)
df.append(results_df, ignore_index=True)
return results
recursive_method(arg)
return df
但是,这不起作用。如果我以这种方式追加, df
总是空的。
我在这里找到了我的问题的答案:appending-to-an-empty-data-frame-in-pandas...如果空的 DataFrame 对象在该方法的范围内,这有效,但不适用于我的情况。根据@DSM 的评论 "but the append doesn't happen in-place, so you'll have to store the output if you want it:"
IOW,我需要这样的东西:
df = df.append(results_df, ignore_index=True)
在我的本地方法中,但这并不能帮助我访问我的外部范围变量 df 以附加到它。
有没有办法让这一切发生?这与用于扩展列表对象内容的 python extend
方法配合得很好(我意识到 DataFrames 不是列表,但是......)。有没有一种类似的方法可以对 DataFrame 对象执行此操作,而不必处理 df
的范围问题?
顺便说一句,Pandas concat
方法也可以,但是我 运行 进入了变量作用域的问题。
在 Python3 中,您可以使用 非本地关键字:
def outer_method():
... do outer scope stuff here
df = pd.DataFrame(columns=['A','B','C','D'])
def recursive_method(arg):
nonlocal df
... do local stuff here
# func returns a data frame to be appended to empty data frame
results_df = func(args)
df = df.append(results_df, ignore_index=True)
return results
return df
但请注意,每次调用 df.append
return 都是一个新的 DataFrame,因此需要将所有旧数据复制到新的 DataFrame 中。如果你在一个循环中执行 N 次,你最终会制作大约 1+2+3+...+N = O(N^2) 个副本——对性能非常不利。
如果您不需要 recursive_method
内的 df
用于除此以外的任何目的
追加,最好追加到一个列表,然后构造
DataFrame(通过调用pd.concat
一次)在recursive_method
完成后:
df = pd.DataFrame(columns=['A','B','C','D'])
data = [df]
def recursive_method(arg, data):
... do stuff here
# func returns a data frame to be appended to empty data frame
results_df = func(args)
data.append(df_join_out)
return results
recursive_method(arg, data)
df = pd.concat(data, ignore_index=True)
这是最佳解决方案 如果您需要做的只是在内部收集数据
recursive_method
并且可以等待构建新的 df
之后
recursive_method
完成。
在Python2中,如果你必须在recursive_method
中使用df
,那么你可以通过
df
作为 recursive_method
的参数,return df
也是 :
df = pd.DataFrame(columns=['A','B','C','D'])
def recursive_method(arg, df):
... do stuff here
results, df = recursive_method(arg, df)
# func returns a data frame to be appended to empty data frame
results_df = func(args)
df = df.append(results_df, ignore_index=True)
return results, df
results, df = recursive_method(arg, df)
但请注意,进行 O(N^2) 复制将付出沉重的代价
如上所述。
为什么 DataFrames 不能 不应该附加到就地:
DataFrame 中的底层数据存储在 NumPy 数组中。中的数据
NumPy 数组来自连续的内存块。有时没有
space 足以将 NumPy 数组的大小调整为更大的连续内存块
即使内存可用——想象一下数组夹在中间
其他数据结构。在那种情况下,为了调整数组的大小,一个新的更大的
必须在其他地方分配内存块,并且所有数据都来自
必须将原始数组复制到新块。一般情况下是做不到的
就地。
DataFrames
确实有一个私有方法,_update_inplace
,它可能是
用于将 DataFrame 的基础数据重定向到新数据。这只是一个
伪就地操作,因为新数据(想想 NumPy 数组)必须是
首先分配(所有服务员复制)。所以使用 _update_inplace
有
两次打击它:它使用了一个(理论上)可能不是的私有方法
在 Pandas 的未来版本中,它会导致 O(N^2) 复制惩罚。
In [231]: df = pd.DataFrame([[0,1,2]])
In [232]: df
Out[232]:
0 1 2
0 0 1 2
In [233]: df._update_inplace(df.append([[3,4,5]]))
In [234]: df
Out[234]:
0 1 2
0 0 1 2
0 3 4 5
我有一个在本地方法范围外初始化的数据框。我想做如下:
def outer_method():
... do outer scope stuff here
df = pd.DataFrame(columns=['A','B','C','D'])
def recursive_method(arg):
... do local stuff here
# func returns a data frame to be appended to empty data frame
results_df = func(args)
df.append(results_df, ignore_index=True)
return results
recursive_method(arg)
return df
但是,这不起作用。如果我以这种方式追加, df
总是空的。
我在这里找到了我的问题的答案:appending-to-an-empty-data-frame-in-pandas...如果空的 DataFrame 对象在该方法的范围内,这有效,但不适用于我的情况。根据@DSM 的评论 "but the append doesn't happen in-place, so you'll have to store the output if you want it:"
IOW,我需要这样的东西:
df = df.append(results_df, ignore_index=True)
在我的本地方法中,但这并不能帮助我访问我的外部范围变量 df 以附加到它。
有没有办法让这一切发生?这与用于扩展列表对象内容的 python extend
方法配合得很好(我意识到 DataFrames 不是列表,但是......)。有没有一种类似的方法可以对 DataFrame 对象执行此操作,而不必处理 df
的范围问题?
顺便说一句,Pandas concat
方法也可以,但是我 运行 进入了变量作用域的问题。
在 Python3 中,您可以使用 非本地关键字:
def outer_method():
... do outer scope stuff here
df = pd.DataFrame(columns=['A','B','C','D'])
def recursive_method(arg):
nonlocal df
... do local stuff here
# func returns a data frame to be appended to empty data frame
results_df = func(args)
df = df.append(results_df, ignore_index=True)
return results
return df
但请注意,每次调用 df.append
return 都是一个新的 DataFrame,因此需要将所有旧数据复制到新的 DataFrame 中。如果你在一个循环中执行 N 次,你最终会制作大约 1+2+3+...+N = O(N^2) 个副本——对性能非常不利。
如果您不需要 recursive_method
内的 df
用于除此以外的任何目的
追加,最好追加到一个列表,然后构造
DataFrame(通过调用pd.concat
一次)在recursive_method
完成后:
df = pd.DataFrame(columns=['A','B','C','D'])
data = [df]
def recursive_method(arg, data):
... do stuff here
# func returns a data frame to be appended to empty data frame
results_df = func(args)
data.append(df_join_out)
return results
recursive_method(arg, data)
df = pd.concat(data, ignore_index=True)
这是最佳解决方案 如果您需要做的只是在内部收集数据
recursive_method
并且可以等待构建新的 df
之后
recursive_method
完成。
在Python2中,如果你必须在recursive_method
中使用df
,那么你可以通过
df
作为 recursive_method
的参数,return df
也是 :
df = pd.DataFrame(columns=['A','B','C','D'])
def recursive_method(arg, df):
... do stuff here
results, df = recursive_method(arg, df)
# func returns a data frame to be appended to empty data frame
results_df = func(args)
df = df.append(results_df, ignore_index=True)
return results, df
results, df = recursive_method(arg, df)
但请注意,进行 O(N^2) 复制将付出沉重的代价 如上所述。
为什么 DataFrames 不能 不应该附加到就地:
DataFrame 中的底层数据存储在 NumPy 数组中。中的数据 NumPy 数组来自连续的内存块。有时没有 space 足以将 NumPy 数组的大小调整为更大的连续内存块 即使内存可用——想象一下数组夹在中间 其他数据结构。在那种情况下,为了调整数组的大小,一个新的更大的 必须在其他地方分配内存块,并且所有数据都来自 必须将原始数组复制到新块。一般情况下是做不到的 就地。
DataFrames
确实有一个私有方法,_update_inplace
,它可能是
用于将 DataFrame 的基础数据重定向到新数据。这只是一个
伪就地操作,因为新数据(想想 NumPy 数组)必须是
首先分配(所有服务员复制)。所以使用 _update_inplace
有
两次打击它:它使用了一个(理论上)可能不是的私有方法
在 Pandas 的未来版本中,它会导致 O(N^2) 复制惩罚。
In [231]: df = pd.DataFrame([[0,1,2]])
In [232]: df
Out[232]:
0 1 2
0 0 1 2
In [233]: df._update_inplace(df.append([[3,4,5]]))
In [234]: df
Out[234]:
0 1 2
0 0 1 2
0 3 4 5