我有一个包含3列(col1、col2和col3)的df,并且我有一个用户输入,可以为列输入值,可以是1、2或3列,也可以是任意组合,比如(col1或col1&col2,或col2&col3,等等)。根据用户输入,我需要选择具有这些值的行。例如,如果我有下面的表:
col1 col2 col3
1 3 3
3 4 5
5 2 1
3 4 2
等等,用户可以只输入col2的值(在本例中为4),然后我必须显示行(2和4),或者如果他们为col1输入(1),那么只显示行(1),我的逻辑公式将是这样的:
x = input1
y = input2
z = imput3
a = df['col1'] == x and df['col2'] == y and df['col1'] == z
因此x, y和z可以是基于输入的任何值,包括nil (nil表示所有)。
对于如何编写这样一个公式的代码有什么建议吗?
使用布尔组合
a = ((df['col1'] == x) | (x is None))
& ((df['col2'] == y) | (y is None))
& ((df['col3'] == z) | (z is None))
df1 = df[a]
None
是通配符。
注意&
和|
不是短路操作符,因此这可能是昂贵的。即使您对列使用了通配符,它仍然会将该列中的所有内容与None
进行比较。一个更好的方法是动态地构造条件。
condition = True
if x is not None:
condition &= df['col1'] == x
if y is not None:
condition &= df['col2'] == y
if z is not None:
condition &= df['col3'] == z
df1 = df[condition]
您可以通过创建列名和条件的字典来更动态地完成此操作。
我最终使用了以下代码:
mask = True
if x:
mask &= (df['col1'] == x)
if y:
mask &= (df['col2'] == y)
if z:
mask &= (df['col3'] == z)
result = df[mask]
你可以有一个通用的解决方案,不管你的数据框架有多少列。
首先构建一个包含列名和查找值的字典,然后对数据框进行索引以查找包含这些值的行号,最后对数据框进行切片以显示必要的行:
import pandas as pd
df = pd.DataFrame(
{
'col1': [1, 3, 5, 3],
'col2': [3, 4, 2, 4],
'col3': [3, 5, 1, 2]
}
)
columns = [f'col{i}' for i in range(1, df.shape[1] + 1)]
query_dict = {}
for c in columns:
try:
query_dict[c] = int(input(f"Enter query for column {c} or Enter to skip: "))
except ValueError:
query_dict[c] = None
rows = []
for k, v in query_dict.items():
rows.extend((df.loc[df[k] == v]).index.values)
df.iloc[rows, :]