我目前有一个带有日期索引的现有Pandas DataFrame,以及每个都有特定名称的列。
对于数据单元格,它们填充了各种浮点值。
我想复制我的DataFrame,但将所有这些值替换为零。
目标是重用DataFrame的结构(维度,索引,列名称),但通过用零替换它们来清除所有当前值。
我目前实现这一目标的方式如下:
df[df > 0] = 0
但是,这不会取代DataFrame中的任何负值。
是否有更通用的方法来填充具有单个公共值的整个现有DataFrame?
提前感谢您的帮助。
答案 0 :(得分:29)
绝对最快的方式,也保留dtypes
,如下:
for col in df.columns:
df[col].values[:] = 0
这直接写入每列的底层numpy数组。我怀疑任何其他方法都会比这更快,因为这不会分配额外的存储空间,也不会通过pandas的dtype
处理。您还可以使用np.issubdtype
仅将数字列清零。如果你有一个混合的dtype
DataFrame,这可能就是你想要的,但当然,如果你的DataFrame是完全数字的,那就没有必要了。
for col in df.columns:
if np.issubdtype(df[col], np.number):
df[col].values[:] = 0
对于小型DataFrame,子类型检查成本相对较高。对于大型DataFrame,将非数字列清零的成本很高。
def make_df(n):
import pandas as pd
df = pd.concat([
pd.Series(range(n), name='int', dtype=int),
pd.Series(range(n), name='float', dtype=float),
pd.date_range(
start='1970-1-1', freq='T', periods=n, name='dt'
).to_series().reset_index(drop=True),
pd.Series(
[chr((i%26)+65) for i in range(n)],
name='string',
dtype='object')
], axis=1)
return df
>>> make_df(5)
int float dt string
0 0 0.0 1970-01-01 00:00:00 A
1 1 1.0 1970-01-01 00:01:00 B
2 2 2.0 1970-01-01 00:02:00 C
3 3 3.0 1970-01-01 00:03:00 D
4 4 4.0 1970-01-01 00:04:00 E
n = 1_000
# All dtypes preserved
%%timeit df = make_df(n)
for col in df.columns:
df[col].values[:] = 0
34.5 µs ± 2.74 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
# All dtypes preserved, non-numeric columns unaltered
%%timeit df = make_df(n)
for col in df.columns:
if np.issubdtype(df[col], np.number):
df[col].values[:] = 0
48 µs ± 3.18 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
n = 10_000
# All dtypes preserved
%%timeit df = make_df(n)
for col in df.columns:
df[col].values[:] = 0
106 µs ± 934 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
# All dtypes preserved, non-numeric columns unaltered
%%timeit df = make_df(n)
for col in df.columns:
if np.issubdtype(df[col], np.number):
df[col].values[:] = 0
54 µs ± 1.43 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
n = 10_000_000
# All dtypes preserved
%%timeit df = make_df(n)
for col in df.columns:
df[col].values[:] = 0
93.6 ms ± 475 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
# All dtypes preserved, non-numeric columns unaltered
%%timeit df = make_df(n)
for col in df.columns:
if np.issubdtype(df[col], np.number):
df[col].values[:] = 0
14.5 ms ± 403 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
我之前曾提出过以下答案,但我现在认为它有害 - 它比上述答案明显慢,而且更难以推理。它的唯一优势是写得更好。
最干净的方法是使用裸露的冒号来引用整个 数据帧。
df[:] = 0
不幸的是
dtype
情况有点模糊,因为每一个 结果数据框中的列将具有相同的dtype
。如果每一个df
的列原来是float
,新的dtypes
仍然是float
。但是,如果单个列是int
或object
,那么似乎就是这样 新的dtypes
将所有设为int
。
答案 1 :(得分:7)
您可以使用replace功能:
df2 = df.replace(df, 0)
答案 2 :(得分:3)
由于您正在尝试制作副本,因此最好只创建一个值为0的新数据框,以及原始数据框中的列和索引:
pd.DataFrame(0, columns=df.columns, index=df.index)
答案 3 :(得分:0)
FYI对我来说,BallpointBen 接受的答案比Joe T Boka提供的.replace()操作快了近两个数量级。两者都是有帮助的。谢谢!
要清楚,BallpointBen描述的快速方法是:
for col in df.columns:
df[col].values[:] = 0
*我本来会对此发表评论,但由于我潜伏了多年,所以我的街头信誉/声誉还不够。我使用timeit.timeit()进行比较。