【问题标题】:Cell reference of pandas data frame, filtering based on specific valuepandas数据框的单元格引用,根据具体值过滤
【发布时间】:2021-12-09 15:41:01
【问题描述】:

我需要获取我的 pandas 数据框中包含值 == 1 的所有区域的单元格引用(行号、列号)。

import pandas as pd
import numpy as np

df = pd.DataFrame({'x': [np.nan, 1, np.nan, np.nan, 1],
                   'y': [np.nan, np.nan, np.nan, np.nan, 1],
                   'z': [1, np.nan, 1, np.nan, np.nan]})

希望得到一个包含两列的最终数据框:行和列,如下所示:

  row  col
0  1    1
1  4    1
2  4    2
3  0    3
4  2    3

【问题讨论】:

    标签: pandas indexing


    【解决方案1】:

    您可以使用numpy.argwhere

    这应该比使用for循环、df.stack等的所有解决方案都要快得多。请看下面的时间安排

    In [145]: import numpy as np
    
    In [146]: res = pd.DataFrame(np.argwhere(df.notnull().values).tolist(), columns=['row', 'col'])
    
    In [147]: res.col = res.col + 1
    
    In [148]: res
    Out[148]: 
       row  col
    0    0    3
    1    1    1
    2    2    3
    3    4    1
    4    4    2
    

    时间安排:

    np.argwhere:

    In [149]: %timeit pd.DataFrame(np.argwhere(df.notnull().values).tolist(), columns=['row', 'col'])
    437 µs ± 4.71 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    

    使用df.stack的@sophocles 解决方案:

    In [151]: %timeit pd.DataFrame(df[df.notna()].stack().index.tolist(),columns=['row','col'])
    1.33 ms ± 5.55 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    

    【讨论】:

    • @sophcles 绝对。因此,最好的答案绝对应该被投赞成票。
    【解决方案2】:

    您可以使用notna() 来获取布尔数据帧,并使用stack() 删除已转换为Falsenan。获取index 并转换为列表,以便您可以轻松转换为DataFrame。

    使用正确的列名将其包装在 pd.DataFrame() 中可以满足您的需求:

    df.columns=[1,2,3]
    pd.DataFrame(df[df.notna()].stack().index.tolist(),columns=['row','col'])
    

       row  col
    0    0    3
    1    1    1
    2    2    3
    3    4    1
    4    4    2
    

    【讨论】:

      【解决方案3】:

      你可以只遍历行和列:

      res_df = pd.DataFrame(columns=['row', 'col'])
      
      for i in range(len(df)):
        for j in range(len(df.columns)):
          if df[df.columns[j]].iloc[i] == 1:
            res_df = res_df.append({'row': i, 'col': j+1}, ignore_index=True)
      
      print(res_df.sort_values(by='col').reset_index(drop=True))
      
        row col
      0   1   1
      1   4   1
      2   4   2
      3   0   3
      4   2   3
      

      【讨论】:

        【解决方案4】:

        你可以试试这个:

        import pandas as pd
        import numpy as np
        
        df = pd.DataFrame({'x': [np.nan, 1, np.nan, np.nan, 1],
                           'y': [np.nan, np.nan, np.nan, np.nan, 1],
                           'z': [1, np.nan, 1, np.nan, np.nan]})
        
        list_indexes = []
        for idx in range(len(df.columns)):
            rows = df.index[df.iloc[:, idx] == 1].tolist()
            for row in rows:
                list_indexes.append((row, idx+1))
        
        final = pd.DataFrame(list_indexes, columns=['row', 'column'])
        print(final)
        

        【讨论】:

          【解决方案5】:

          你可以这样做:

          df.columns=list(range(1,len(df.columns)+1))
          
             1    2   3
          0   NaN NaN 1.0
          1   1.0 NaN NaN
          2   NaN NaN 1.0
          3   NaN NaN NaN
          4   1.0 1.0 NaN
          
          new_df = df.stack().reset_index().rename(columns = {'level_0':'row', 'level_1':'col'})[['row', 'col']]
          
             row  col
          0    0    3
          1    1    1
          2    2    3
          3    4    1
          4    4    2
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-07-12
            • 2017-11-03
            • 1970-01-01
            • 1970-01-01
            • 2020-01-18
            • 2021-08-30
            • 1970-01-01
            • 2018-03-27
            相关资源
            最近更新 更多