【问题标题】:Create a DataFrame based on a shape with default values基于具有默认值的形状创建 DataFrame
【发布时间】:2019-06-03 02:35:32
【问题描述】:

我有一个接收 df 的函数。 我试图让它返回一个具有相同形状但默认值的 df(在我的示例中为 True)。

我有时会得到一个系列作为 df(仅一个列)。

我设法为一个系列找到了一些东西:

def func(df):
    return pd.Series([True for i in range(df.shape[0])])

我还管理了一个 df:

def func(df):
     return df.apply(lambda x: True)

但这似乎资源不足,我试图找到一种快速而优雅的方式来实现这一目标。

【问题讨论】:

  • df[:]=True 呢?
  • 有趣。这有效,但它改变了 df 本身并且不返回新的 df。任何想法它是多么“昂贵”,资源明智?
  • pd.DataFrame().reindex_like(df).fillna(True) 应该非常有效。见stackoverflow.com/questions/27467730/…
  • @ayhan 这不适用于系列:/

标签: python pandas


【解决方案1】:

编辑 3为一些已发布的答案添加 %timeit

样本:

n = np.arange(900000).reshape(300000, 3)
df = pd.DataFrame(n, columns = list('abc'))

%timeit 结果:

In [19]: %timeit pd.DataFrame().reindex_like(df).fillna(True)
336 ms ± 13.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [20]: %timeit ~df.eq(np.nan)
2.7 ms ± 175 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [21]: %timeit df.where(df.isna()).fillna(True)
332 ms ± 11.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [22]: %%timeit
    ...: df1=df.copy()
    ...: df1[:]=True
    ...:
7.39 ms ± 339 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

所以,~df.eq(np.nan) 是最快的


编辑 2: 使用“NaN”的特殊功能添加另一个方法,即NaN == NaN return False。因此,将整个dfNaN 进行比较。它将返回所有False。然后,使用否定运算符'~' 将所有内容变为True

~df.eq(np.nan)

Out[1386]:
      a     b     c
0  True  True  True
1  True  True  True
2  True  True  True

编辑:(添加说明

df.whereseries.where 上的文档

df.isnaNaN 上返回True,在non-NaN 上返回False。我使用df.isna 创建一个布尔掩码以与.where 一起使用。在掩码True 上,.where 保持相同的值,即NaN。在掩码 False 上,.where 替换为 replaced-value。我没有指定replaced-value,所以.where 默认为NaN

这意味着整个df 将转向所有NaN,无论它具有什么值。最后,fillnaTrue

此方法适用于数据框和系列


IIUC,您想从当前的 df 创建一个 new_df,其中所有值都变为 True。如果是这种情况,则不需要函数。

一个简单的方法应该可以工作:

样本数据:

df:
   a  b  c
0  0  1  2
1  3  4  5
2  6  7  8

df.where(df.isna()).fillna(True)

Out[1374]:
      a     b     c
0  True  True  True
1  True  True  True
2  True  True  True

【讨论】:

  • 您能详细说明一下答案吗? df.isna() 应该返回缺失值。这对所有值有何影响?
  • @NotSoShabby:我添加了另一种使用NaN 比较和否定的方法。检查我的更新
  • ~df.eq(np.nan) 绝对是最优雅的方式。你知道这是否也有效吗?
  • @NotSoShabby:我在这里添加了%timeit 以获得一些答案。根据结果​​,~df.eq(np.nan) 最快。
【解决方案2】:

您可以编写一个函数,它将df 作为输入并返回一个形状与True 相同的df1

def my_true(df):
    df1=df.copy()
    df1[:]=True
    return df1

my_true(df)

      a     b     c
0  True  True  True
1  True  True  True
2  True  True  True

【讨论】:

    【解决方案3】:

    根据您的df 上的数据类型,可以有多种方法。但是,以下方法与 df 中的数据类型无关。

    import numpy as np
    def create_default_df(df, replace_with):
        return pd.DataFrame(np.full(df.shape,replace_with), columns = df.columns, index = df.index)
    

    这是一个测试用例:

    import pandas as pd
    dat = pd.DataFrame({'a':[1,2,3], 'b': ['x', None, 'y']})
    default_dat = create_default_df(ser, 0)
    print(default_dat)
    

    结果是

       a  b
    0  0  0
    1  0  0
    2  0  0
    

    编辑 - 用于系列

    ser = pd.Series([1,2,3])
    default_dat = create_default_df(dat, 0)
    print(default_dat)
    

    输出是

       0
    0  0
    1  0
    2  0
    

    【讨论】:

    • 虽然这不适用于系列:/。不过,这对完整的 DF 来说是件好事
    • 你试过一个系列吗?该功能对我来说很好。
    • 我也添加了一个系列的用例。由于系列没有 colname(除非您明确提及名称),输出将始终将 col 命名为 0。检查并让我知道这是否能解决您的问题
    【解决方案4】:
    def rep_values(obj, value):
        obj[:] = value  //Change condition based on your needs
        return obj
    
    In [27]: df
    Out[27]: 
       0  1  2
    0  0  0  0
    1  1  2  3
    In [28]: df = rep_values(df, 1)
    
    In [29]: df
    Out[29]: 
       0  1  2
    0  1  1  1
    1  1  1  1
    
    In [30]: s = pd.Series([1,2,3])
    
    In [31]: s = rep_values(s, 1)
    
    In [32]: s
    Out[32]: 
    0    1
    1    1
    2    1
    dtype: int64
    

    【讨论】:

    • 我试图在没有条件的情况下这样做。只是形状(例如我不介意它是否为空)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-02
    • 2023-03-28
    • 1970-01-01
    • 2014-03-13
    • 2022-01-07
    相关资源
    最近更新 更多