代码之家  ›  专栏  ›  技术社区  ›  Jeffrey Benjamin Brown

Pandas:将知道列类型的函数应用于数据帧的每一列

  •  2
  • Jeffrey Benjamin Brown  · 技术社区  · 6 年前

    目标

    我想对数据框中的每一列应用一个依赖于输入列类型的函数。考虑以下数据帧:

    df = pd.DataFrame( [["a",1],["b",2]], columns = ["string","num"] )
    

    >>> df["num"].dtype            
    dtype('int64')
    >>> df["num"].dtype in ["int64"]
    True
    

    >>> df . apply( lambda column: column.sum() )
    string    ab
    num        3
    dtype: object
    

    但是如果我让函数依赖于列的类型,我会得到垃圾:

    >>> df . apply( lambda column:
    ...             np.nan if not column.dtype in ['float64','float32','int32','int64']
    ...             else column.sum() )
    string   NaN
    num      NaN
    dtype: float64
    

    动机

    有些解决方案基本上涉及删除非数字列,但实际上我需要保留它们。原因是我试图在df.describe的结果后面加一行,该行计算每列中的零。下面是一个类似函数的示例:

    def describe_plus(df):
      most_stats = df.describe()
      missing_stat = pd.DataFrame( df.isnull().sum()
                                 , columns = ["missing"]
                                 ).transpose()
      length_stat = pd.DataFrame( [[len(df) for _ in df.columns]]
                                , index = ["length"]
                                , columns = df.columns )
      return length_stat.append( missing_stat.append( most_stats ) )
    

    调用它可以得到pd.descripe的普通输出,以及每列中缺少的长度和数字:

    >>> describe_plus( df )
                  num  string
    length   2.000000     2.0
    missing  0.000000     0.0
    count    2.000000     NaN
    mean     1.000000     NaN
    std      1.414214     NaN
    min      0.000000     NaN
    25%      0.500000     NaN
    50%      1.000000     NaN
    75%      1.500000     NaN
    max      2.000000     NaN
    

    除了length和missing之外,我还想添加第三行来描述\u plus,它计算每列中的零数,或者为不是数字的列提供NaN。

    编辑:RafaelC的解决方案,在这个框架中

    诀窍是丢弃那些非数字变量,计算摘要统计信息,然后简单地附加其他统计信息(这些统计信息是在每一列上定义的,甚至是非数字的)。

    def describe_plus_plus(df):
      nums = df.select_dtypes(include=[np.number])
      zeroes = pd.DataFrame( [nums.apply( lambda col: len( col[col==0] ) / 
    len(nums) )] )
      return zeroes.append( describe_plus( df ) )
    

    它在行动中的例子:

    >>> df = pd.DataFrame( [[0,0,0,""],[0,0,1,"a"],[0,1,2,"b"]], columns = ["none","1/3","2/3","string"] )
    >>> describe_plus_plus( df )
                  1/3       2/3  none  string
    0        0.666667  0.333333   1.0     NaN
    length   3.000000  3.000000   3.0     3.0
    missing  0.000000  0.000000   0.0     0.0
    count    3.000000  3.000000   3.0     NaN
    mean     0.333333  1.000000   0.0     NaN
    std      0.577350  1.000000   0.0     NaN
    min      0.000000  0.000000   0.0     NaN
    25%      0.000000  0.500000   0.0     NaN
    50%      0.000000  1.000000   0.0     NaN
    75%      0.500000  1.500000   0.0     NaN
    max      1.000000  2.000000   0.0     NaN
    
    1 回复  |  直到 6 年前
        1
  •  3
  •   rafaelc    6 年前

    如果您有允许类型的列表,只需使用 loc

    allowed_types = [np.float64, np.float32,np.int32, np.int64]
    mask = df.dtypes.isin(allowed_types)
    df.loc[:, mask].sum()
    

    然而,一个可能更好的方法是使用 select_dtypes np.number 如果只想选择数字列,则将其作为父数据类型。

    df.select_dtypes(include=[np.number])
    

    当然,可以改变 [np.number] 在你的名单上 allowed_types