如何将现有Pandas DataFrame的所有值设置为零?

时间:2017-03-06 22:25:44

标签: python pandas dataframe

我目前有一个带有日期索引的现有Pandas DataFrame,以及每个都有特定名称的列。

对于数据单元格,它们填充了各种浮点值。

我想复制我的DataFrame,但将所有这些值替换为零。

目标是重用DataFrame的结构(维度,索引,列名称),但通过用零替换它们来清除所有当前值。

我目前实现这一目标的方式如下:

df[df > 0] = 0

但是,这不会取代DataFrame中的任何负值。

是否有更通用的方法来填充具有单个公共值的整个现有DataFrame?

提前感谢您的帮助。

4 个答案:

答案 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

小型DataFrame

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)

Medium DataFrame

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)

大型DataFrame

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。但是,如果单个列是intobject,那么似乎就是这样   新的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()进行比较。

相关问题