slice df where column looks like [(A, 3), (-A, 1), (-C, 4)] 使用像所有行这样的标准 A>5 等

slice df where column looks like [(A, 3), (-A, 1), (-C, 4)] using criteria like all rows such that A>5 etc

我有一个数据框,其中有一列如下所示:

dct = {}
for x in range(0,1000000):
    test = {'A': np.random.randint(1,5), '-A': np.random.randint(1,5), '-C': np.random.randint(1,5)}
    dct[str(x)+'_key'] = test

df = pd.DataFrame([[d.items()] for d in dct.values()])

df.tail()
Out[208]:

    0
    1299995 [(A, 3), (-A, 1), (-C, 4)]
    1299996 [(A, 2), (-A, 4), (-C, 1)]
    1299997 [(A, 3), (-A, 1), (-C, 3)]
    1299998 [(A, 2), (-A, 2), (-C, 1)]
    1299999 [(A, 1), (-A, 2), (-C, 4)]

我的数据框中有大约 130 万行。还有其他专栏,但与这个问题无关。

在我的现实生活中,每行计数的总和 = 10。但我不知道如何使用 np.random.randint() 创建一个示例数据框,以满足每行的总计数必须等于10. 有效字母表是以下 (A,B,C,D,-A,-B,-C,-D) 中的任何一个。

因此,每一行都从该集合中选择,总限制为 count = 10。所以一行可以有这样的东西:

[(A, 10)]
[(B, 3), (-D, 1), (-A, 6)]
[(A, 2), (B, 1), (-C, 2),(-D,5)]

无论如何,上面的例子 df 应该足够了。

我想要做的是能够使用类似于以下问题的标准使用此列对这个 df 进行切片:

-all rows such that the number of A > 5 AND B < 0 (or not existent) AND -D > 2

问题可以是单条件的,也可以是多条件的。

无论如何,我不确定如何有效地执行此操作,尤其是因为每一行都由元组组成。

很简单,将列转换为字典:

df[0] = df[0].apply(dict)

现在,无论您的查询是什么,您都可以将其写为:

def query(row, key, value, cond):
    return eval(str(row.get(key)) + cond + str(value))

df.apply(query, key='A', value=2, cond='>', axis=1)

或简称为:

df.apply(lambda x: x[0].get('A') > 2, axis=1)

如果您可以拆分元组列,这应该可行,只需将条件替换为您的数字即可。我将这些用于示例数据:

def f(x, var):
    tup_list = list(x)
    for t in tup_list:
        if t[0] == var:
        return t[1]
    return np.NaN

df.columns = ['col']
for var in ['A', '-A', 'B', '-B', 'C', '-C', 'D', '-D']:
    df[var] = df['col'].apply(lambda x: f(x, var))

df2 = df.loc[(df['A'] > 3) & ((df['-A'] < 3) & (df['B'] is not np.NaN)) & (df['-C'] > 2)]