我想基于一个或多个列以及pandas数据帧中这些列中的一个或多个值创建逻辑掩码。然后应将这些掩码应用于另一列。在最简单的情况下,掩码可能如下所示:
mask = data['a'] == 4
newData = data['c'][mask]
然而,更复杂的情况也是可能的:
mask = ((data['a'] == 4) | (data['a'] == 8)) & ((data['b'] == 1) | (data['b'] == 5))
newData = data['c'][mask]
此外,可能还需要多个掩码。主要问题是我事先不知道
因为这些信息将由用户提供。
我认为我可以要求用户按以下方式创建输入文件:
# <maskName> - <columnName>: <columnValue(s)> - <columnName>: <columnValue(s)> - etc.
maskA - a: 4, 8 - b: 1, 5 - c: 1
maskB - a: 0, 8 - c: 2, 6, 10
targetColumn: d
然后我可以读取输入文件并循环它。通过适当地处理这些线,我可以识别所需掩码的数量,相关列,相关值以及应该应用掩码的列。我还可以将此信息添加到列表和/或词典中。
但是,我不确定如何最好地处理我事先不知道掩码/列/值的数量以及如何在我知道后生成适当的掩码的问题。任何帮助将不胜感激。
答案 0 :(得分:1)
因为您可以将字符串传递给df.query()
,所以只要您可以将输入格式转换为字符串,找到所需的子集就非常简单。我为你的输入格式编写的解析器并不是非常优雅,但希望你能得到这个想法:
import pandas as pd
import numpy as np
maskA_str = "maskA - a: 4, 8 - b: 1, 5 - c: 1"
df = pd.DataFrame(
{'a': np.random.randint(1, 10, 100),
'b': np.random.randint(1, 10, 100),
'c': np.random.randint(1, 10, 100)}
)
def create_query_str(mask_str):
mask_name, column_conds = mask_str.split('-')[0], mask_str.split('-')[1:]
query_str = '('
column_strs =[]
for cond in column_conds:
cond_str = '('
column, vals = cond.split(':')
column = column.strip()
test_strs = ['{c} == {v}'.format(c=column, v=val.strip())
for val in vals.split(',')]
cond_str += ' | '.join(test_strs)
cond_str += ')'
column_strs.append(cond_str)
query_str += ' & '.join(column_strs)
query_str += ')'
return query_str
create_query_str(maskA_str)
Out[17]: '((a == 4 | a == 8) & (b == 1 | b == 5) & (c == 1))'
# Can now be used directly in df.query()
df.query(create_query_str(maskA_str))