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

发布于 2021-01-29 15:24:22

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

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

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

目的是重用DataFrame的结构(尺寸,索引,列名),但通过将其替换为零来清除所有当前值。

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

df[df > 0] = 0

但是,这不会替换DataFrame中的任何负值。

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

预先感谢您的帮助。

关注者
0
被浏览
140
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    也可以保留的绝对最快的方法dtypes如下:

    for col in df.columns:
        df[col].values[:] = 0
    

    这将直接写入每个列的基础numpy数组。我怀疑其他任何方法都不会比这更快,因为这不会分配额外的存储空间并且不会通过熊猫的dtype处理。您也np.issubdtype可以只将数字列清零。如果您有混合的dtypeDataFrame,这可能就是您想要的,但是,如果您的DataFrame已经是完全数字的,那么这当然不是必需的。

    for col in df.columns:
        if np.issubdtype(df[col].dtype, np.number):
            df[col].values[:] = 0
    

    对于小型DataFrame,子类型检查会花费一些成本。但是,将非数字列清零的成本非常高,因此,如果不确定DataFrame是否完全为数字,则可能应包括issubdtype检查。


    时序比较

    设定

    import pandas as pd
    import numpy as np
    
    def make_df(n, only_numeric):
        series = [
            pd.Series(range(n), name="int", dtype=int),
            pd.Series(range(n), name="float", dtype=float),
        ]
        if only_numeric:
            series.extend(
                [
                    pd.Series(range(n, 2 * n), name="int2", dtype=int),
                    pd.Series(range(n, 2 * n), name="float2", dtype=float),
                ]
            )
        else:
            series.extend(
                [
                    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",
                    ),
                ]
            )
    
        return pd.concat(series, axis=1)
    

    >>> make_df(5, True)
       int  float  int2  float2
    0    0    0.0     5     5.0
    1    1    1.0     6     6.0
    2    2    2.0     7     7.0
    3    3    3.0     8     8.0
    4    4    4.0     9     9.0
    
    >>> make_df(5, False)
       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 = 10_000
    
    # Numeric df, no issubdtype check
    %%timeit df = make_df(n, True)
    for col in df.columns:
        df[col].values[:] = 0
    36.1 µs ± 510 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    
    # Numeric df, yes issubdtype check
    %%timeit df = make_df(n, True)
    for col in df.columns:
        if np.issubdtype(df[col].dtype, np.number):
            df[col].values[:] = 0
    53 µs ± 645 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    
    # Non-numeric df, no issubdtype check
    %%timeit df = make_df(n, False)
    for col in df.columns:
        df[col].values[:] = 0
    113 µs ± 391 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    
    # Non-numeric df, yes issubdtype check
    %%timeit df = make_df(n, False)
    for col in df.columns:
        if np.issubdtype(df[col].dtype, np.number):
            df[col].values[:] = 0
    39.4 µs ± 1.91 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    

    大数据框

    n = 10_000_000
    
    # Numeric df, no issubdtype check
    %%timeit df = make_df(n, True)
    for col in df.columns:
        df[col].values[:] = 0
    38.7 ms ± 151 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
    
    # Numeric df, yes issubdtype check
    %%timeit df = make_df(n, True)
    for col in df.columns:
        if np.issubdtype(df[col].dtype, np.number):
            df[col].values[:] = 0
    39.1 ms ± 556 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
    
    # Non-numeric df, no issubdtype check
    %%timeit df = make_df(n, False)
    for col in df.columns:
        df[col].values[:] = 0
    99.5 ms ± 748 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
    
    # Non-numeric df, yes issubdtype check
    %%timeit df = make_df(n, False)
    for col in df.columns:
        if np.issubdtype(df[col].dtype, np.number):
            df[col].values[:] = 0
    17.8 ms ± 228 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    

    我之前曾建议过以下答案,但现在我认为这是有害的-它比上述答案慢得多,也很难推理。 它唯一的优点是写得更好。

    最干净的方法是使用裸冒号引用整个数据框。

    df[:] = 0
    

    不幸的是,dtype情况有点模糊,因为结果数据帧中的每一列都将具有相同的值dtype。如果的每一列df都是原来的float,则新列dtypes仍然是
    float。但是,如果一列是intobject,似乎新的dtypes意愿 可以int



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看