使用包含 shift 方法的动态表达式获取 pandas DataFrame 的子集
Get subset of pandas DataFrame using dynamic expression including the shift method
我有这个 pandas
数据框:
In [1]: import pandas as pd
In [2]: df = pd.DataFrame([[43.97, 43.97, 43.75, 43.94],
...: [43.97, 44.25, 43.97, 44.25],
...: [44.22, 44.38, 44.12, 44.34],
...: [44.41, 44.84, 44.38, 44.81],
...: [44.97, 45.09, 44.47, 45.00],
...: [44.97, 45.06, 44.72, 44.97],
...: [44.97, 45.12, 44.91, 44.97]],
...: columns=['O', 'H', 'L', 'C'])
感谢@JoeKington,我能够使用这个表达式得到它的一个子集:
In [3]: values = df[(df.C > df.H.shift(2)) & (df.H > df.H.shift(1))]
In [4]: print values
O H L C
2 44.22 44.38 44.12 44.34
3 44.41 44.84 44.38 44.81
4 44.97 45.09 44.47 45.00
我想做的是进行一系列比较,例如:
C0 > L0 AND L0 > H2 AND H2 > L1 AND L1 > L2
或
H0 > C0 AND C0 > H1 AND H1 > C1 AND C1 > H2 AND H2 > L1 AND L1 > L2
并将它们转换成可用于 slice/filter/query 数据框的东西。我可以毫无问题地使用其中一个字符串并创建一个看起来像这样的字符串。
(df.C > df.L) & (df.L > df.H.shift(2)) & (df.H.shift(2) > df.L.shift(1)) & (df.L.shift(1) > df.L.shift(2))
我们称这个字符串为条件。现在,如果我想将它用于 return 数组的一个子集,我不能执行以下操作,因为这里不需要字符串。
values = df[condition]
我尝试使用这样的查询方法 values = df.query(condition)
,但我认为 shift
导致它失败,因为我收到此错误:NotImplementedError: 'Call' nodes are not implemented
我已通读 pandas
文档并搜索了数小时的解决方案,但没有找到。我是 python
、pandas
和 numpy
的新手。非常感谢任何指导。
使用字符串中的公式通常是失误的标志,但如果您已经有了它们,那么我们不妨使用它们。像
s = "C0 > L0 AND L0 > H2 AND H2 > L1 AND L1 > L2"
s = s.replace(" AND ", " and ")
shifted_cols = sorted({term for term in s.split() if
term[0].isalpha() and term.lower() not in {"and", "or"}})
cshifts = [(c, c[0], int(c[1:])) for c in shifted_cols]
df_shift = pd.DataFrame({col: df[base_col].shift(s) for col, base_col, s in cshifts})
df.loc[df_shift.eval(s)]
会给
>>> df.loc[df_shift.eval(s)]
O H L C
3 44.41 44.84 44.38 44.81
之所以可行,是因为我们发现了我们需要的移位列:
>>> shifted_cols
['C0', 'H2', 'L0', 'L1', 'L2']
将其分解为 column + shift(这里的列都是一个字母,所以我做了尽可能简单的事情,这不是很健壮,但是切换到更聪明的东西是微不足道的):
>>> cshifts
[('C0', 'C', 0), ('H2', 'H', 2), ('L0', 'L', 0), ('L1', 'L', 1), ('L2', 'L', 2)]
然后我们构建一个临时数据框,我们可以在上面评估我们的字符串:
>>> df_shift
C0 H2 L0 L1 L2
0 43.94 NaN 43.75 NaN NaN
1 44.25 NaN 43.97 43.75 NaN
2 44.34 43.97 44.12 43.97 43.75
3 44.81 44.25 44.38 44.12 43.97
4 45.00 44.38 44.47 44.38 44.12
5 44.97 44.84 44.72 44.47 44.38
6 44.97 45.09 44.91 44.72 44.47
>>> df_shift.eval(s)
0 False
1 False
2 False
3 True
4 False
5 False
6 False
dtype: bool
我们最终用它来索引我们的原始框架。
我有这个 pandas
数据框:
In [1]: import pandas as pd
In [2]: df = pd.DataFrame([[43.97, 43.97, 43.75, 43.94],
...: [43.97, 44.25, 43.97, 44.25],
...: [44.22, 44.38, 44.12, 44.34],
...: [44.41, 44.84, 44.38, 44.81],
...: [44.97, 45.09, 44.47, 45.00],
...: [44.97, 45.06, 44.72, 44.97],
...: [44.97, 45.12, 44.91, 44.97]],
...: columns=['O', 'H', 'L', 'C'])
感谢@JoeKington,我能够使用这个表达式得到它的一个子集:
In [3]: values = df[(df.C > df.H.shift(2)) & (df.H > df.H.shift(1))]
In [4]: print values
O H L C
2 44.22 44.38 44.12 44.34
3 44.41 44.84 44.38 44.81
4 44.97 45.09 44.47 45.00
我想做的是进行一系列比较,例如:
C0 > L0 AND L0 > H2 AND H2 > L1 AND L1 > L2
或
H0 > C0 AND C0 > H1 AND H1 > C1 AND C1 > H2 AND H2 > L1 AND L1 > L2
并将它们转换成可用于 slice/filter/query 数据框的东西。我可以毫无问题地使用其中一个字符串并创建一个看起来像这样的字符串。
(df.C > df.L) & (df.L > df.H.shift(2)) & (df.H.shift(2) > df.L.shift(1)) & (df.L.shift(1) > df.L.shift(2))
我们称这个字符串为条件。现在,如果我想将它用于 return 数组的一个子集,我不能执行以下操作,因为这里不需要字符串。
values = df[condition]
我尝试使用这样的查询方法 values = df.query(condition)
,但我认为 shift
导致它失败,因为我收到此错误:NotImplementedError: 'Call' nodes are not implemented
我已通读 pandas
文档并搜索了数小时的解决方案,但没有找到。我是 python
、pandas
和 numpy
的新手。非常感谢任何指导。
使用字符串中的公式通常是失误的标志,但如果您已经有了它们,那么我们不妨使用它们。像
s = "C0 > L0 AND L0 > H2 AND H2 > L1 AND L1 > L2"
s = s.replace(" AND ", " and ")
shifted_cols = sorted({term for term in s.split() if
term[0].isalpha() and term.lower() not in {"and", "or"}})
cshifts = [(c, c[0], int(c[1:])) for c in shifted_cols]
df_shift = pd.DataFrame({col: df[base_col].shift(s) for col, base_col, s in cshifts})
df.loc[df_shift.eval(s)]
会给
>>> df.loc[df_shift.eval(s)]
O H L C
3 44.41 44.84 44.38 44.81
之所以可行,是因为我们发现了我们需要的移位列:
>>> shifted_cols
['C0', 'H2', 'L0', 'L1', 'L2']
将其分解为 column + shift(这里的列都是一个字母,所以我做了尽可能简单的事情,这不是很健壮,但是切换到更聪明的东西是微不足道的):
>>> cshifts
[('C0', 'C', 0), ('H2', 'H', 2), ('L0', 'L', 0), ('L1', 'L', 1), ('L2', 'L', 2)]
然后我们构建一个临时数据框,我们可以在上面评估我们的字符串:
>>> df_shift
C0 H2 L0 L1 L2
0 43.94 NaN 43.75 NaN NaN
1 44.25 NaN 43.97 43.75 NaN
2 44.34 43.97 44.12 43.97 43.75
3 44.81 44.25 44.38 44.12 43.97
4 45.00 44.38 44.47 44.38 44.12
5 44.97 44.84 44.72 44.47 44.38
6 44.97 45.09 44.91 44.72 44.47
>>> df_shift.eval(s)
0 False
1 False
2 False
3 True
4 False
5 False
6 False
dtype: bool
我们最终用它来索引我们的原始框架。