【问题标题】:get column names using criteria and column value using pandas?使用条件获取列名,使用熊猫获取列值?
【发布时间】:2021-10-01 13:11:31
【问题描述】:

我有一个如下所示的数据框

df = pd.DataFrame({'sub_id': [101,101,101,102,102,103,104],
                   'test_status':['Y','N','Yes','No','Not sure','NOT SURE','YES'],
                   'remarks':[np.nan,"testvalue",np.nan,"ilike","wild",np.nan,"test"],
                   'reg_value':['YES','NO','Y','N','SURE','YES','no'],
                   'TEST':['RES','YES','SAF','YWQTEU','JHLK','1265','QEEU']})

基本上,我想做以下事情

a) 从下面给出的response 列表中获取仅具有值的列的名称

response = ['Y','y','YES','Yes','yes','NO','No','no','N','n','NOT SURE','Not sure','not sure','sure','SURE','Sure']

该列不应包含除response list 中提及的值之外的任何其他值。

例如:column Test 不应出现在输出中,因为与 YES 一起,它包含其他不在 response 列表中的值。

所以,我尝试了以下但输出不正确。不知道如何排除TEST 列。

df.apply(lambda row: row[row.isin(response)].index.tolist(), axis=1)

我希望我的输出如下所示

op_col_list = ['test_status','reg_value']

所以,我有两个问题

a) 如何排除TEST 列以供考虑?

b) 如何使response 列表优雅。如您所见,由于大写和小写表示,这些值正在重复。无论如何要使列表不区分大小写

【问题讨论】:

    标签: python python-3.x pandas dataframe series


    【解决方案1】:

    为了处理不区分大小写的问题,我们可以使用str.fullmatchcase=False

    # These can be any case:
    response = ['Y', 'YES', 'NO', 'N', 'NOT SURE', 'SURE']
    
    # Create a Regex pattern:
    pattern = f'{"|".join(response)}'
    
    # Apply to DataFrame columns
    # (selected using loc can choose only columns needed):
    cols = (
        df.loc[:, 'test_status':'reg_value']
            .apply(lambda s: s.str.fullmatch(pattern, case=False).all())
    )
    
    # Filter With Results:
    cols = cols.index[cols].tolist()
    

    cols 过滤前:

    test_status     True
    remarks        False
    reg_value       True
    dtype: bool
    

    cols 过滤后和tolist:

    ['test_status', 'reg_value']
    

    *fullmatch 将检查单元格是否包含模式中的值。如果要查找包含响应值的单元格,也可以使用str.contains

    【讨论】:

      【解决方案2】:

      使用isin 并只保留所有行都为真的列:

      >>> df.columns[df.isin(response).all()].tolist()
      ['test_status', 'reg_value']
      

      修改response更优雅:

      resp = fr"({'|'.join(set([r.lower() for r in response]))})
      
      >>> df.select_dtypes('object').columns[df.select_dtypes('object').stack()
                                               .str.fullmatch(resp, case=False)
                                               .unstack().all()].tolist()
      
      ['test_status', 'reg_value']
      
      
      >>> resp
      '(sure|not sure|yes|y|no|n)'
      

      【讨论】:

      • @TheGreat。我更新了我的答案。现在response 更优雅了:-)
      【解决方案3】:

      如果您想让它不区分大小写,这可以帮助您:

      response_lower = ['yes', 'not sure', 'n', 'y', 'no', 'sure']
      
      searched_features = []
      for feature in df:
          if df[feature].map(str).str.lower().isin(response_lower).mean() == 1:
              searched_features.append(feature)
      searched_features
      

      【讨论】:

        猜你喜欢
        • 2020-06-13
        • 2020-11-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-25
        • 1970-01-01
        • 1970-01-01
        • 2019-04-04
        相关资源
        最近更新 更多