代码之家  ›  专栏  ›  技术社区  ›  splinter

基于熊猫数据帧内堆叠列的数据帧加长

  •  2
  • splinter  · 技术社区  · 7 年前

    我正在寻找一个实现以下功能的函数。最好在示例中显示。考虑:

    pd.DataFrame([ [1, 2, 3 ], [4, 5, np.nan ]], columns=['x', 'y1', 'y2'])
    

    看起来像:

       x  y1   y2
    0  1   2  3
    1  4   5  NaN
    

    我想合作 y1 y2 列,必要时延长数据名称,以便输出:

       x  y
    0  1   2  
    1  1   3  
    2  4   5  
    

    也就是说,每个组合都有一行 x Y1 X Y2 . 我正在寻找一个相对有效的函数,因为我有多个 y S和许多行。

    3 回复  |  直到 7 年前
        1
  •  1
  •   Divakar    7 年前

    这是一个基于numpy的,因为你在寻找性能-

    def gather_columns(df):
        col_mask = [i.startswith('y') for i in df.columns]
        ally_vals = df.iloc[:,col_mask].values
        y_valid_mask = ~np.isnan(ally_vals)
    
        reps = np.count_nonzero(y_valid_mask, axis=1)
        x_vals = np.repeat(df.x.values, reps)
        y_vals = ally_vals[y_valid_mask]
        return pd.DataFrame({'x':x_vals, 'y':y_vals})
    

    样品运行-

    In [78]: df #(added more cols for variety)
    Out[78]: 
       x  y1   y2   y5   y7
    0  1   2  3.0  NaN  NaN
    1  4   5  NaN  6.0  7.0
    
    In [79]: gather_columns(df)
    Out[79]: 
       x    y
    0  1  2.0
    1  1  3.0
    2  4  5.0
    3  4  6.0
    4  4  7.0
    

    如果 y 列总是从第二列开始一直到最后,我们可以简单地对数据帧进行切片,从而进一步提高性能,就像这样。-

    def gather_columns_v2(df):
        ally_vals = df.iloc[:,1:].values
        y_valid_mask = ~np.isnan(ally_vals)
    
        reps = np.count_nonzero(y_valid_mask, axis=1)
        x_vals = np.repeat(df.x.values, reps)
        y_vals = ally_vals[y_valid_mask]
        return pd.DataFrame({'x':x_vals, 'y':y_vals})
    
        2
  •  3
  •   Bharath M Shetty    7 年前

    你可以用 stack 完成任务,即

    pd.DataFrame(df.set_index('x').stack().reset_index(level=0).values,columns=['x','y'])
    
         x    y
    0  1.0  2.0
    1  1.0  3.0
    2  4.0  5.0
    
        3
  •  2
  •   Mazdak    7 年前

    根据每行中非空值的计数重复第一列中的所有项。然后只需使用其他列中非空值的其余部分来创建最终的数据帧。你可以用 DataFrame.count() 方法来计算非空值和 numpy.repeat() 根据各自的计数数组重复一个数组。

    >>> rest = df.loc[:,'y1':]
    >>> pd.DataFrame({'x': np.repeat(df['x'], rest.count(1)).values,
                      'y': rest.values[rest.notna()]})
    

    演示:

    >>> df
        x   y1   y2   y3   y4
    0   1  2.0  3.0  NaN  6.0
    1   4  5.0  NaN  9.0  3.0
    2  10  NaN  NaN  NaN  NaN
    3   9  NaN  NaN  6.0  NaN
    4   7  6.0  NaN  NaN  NaN
    
    >>> rest = df.loc[:,'y1':]
    >>> pd.DataFrame({'x': np.repeat(df['x'], rest.count(1)).values,
                      'y': rest.values[rest.notna()]})
       x    y
    0  1  2.0
    1  1  3.0
    2  1  6.0
    3  4  5.0
    4  4  9.0
    5  4  3.0
    6  9  6.0
    7  7  6.0