使用条件获取列名,使用 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.fullmatch
和 case=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
我有一个如下所示的数据框
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.fullmatch
和 case=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