使用条件获取列名,使用 pandas 获取列值?

get column names using criteria and column value using pandas?

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

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 列表优雅。正如您所看到的,由于大写和小写表示,值是重复的。无论如何要使列表不区分大小写

使用 isin 并仅保留所有行都为 True 的列:

>>> 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)'

为了处理不区分大小写的问题,我们可以使用 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

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

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