【发布时间】:2016-02-19 07:58:43
【问题描述】:
(更新:添加desired数据框)
首先让我说我相当有信心几年前我找到了解决这个问题的方法,但我无法重新找到那个解决方案。
解决类似问题但未解决我的特定问题的问题包括:
- Efficiently select rows that match one of several values in Pandas DataFrame
- Efficiently adding calculated rows based on index values to a pandas DataFrame
- Compare Python Pandas DataFrames for matching rows
问题
假设我有一个包含许多正在处理的列的数据框:
big = pd.DataFrame({'match_1': [11, 12, 51, 52]})
big
match_1
0 11
1 12
2 51
3 52
我还有更小的数据框,理论上,它将一些条件语句映射到所需的值:
# A smaller dataframe that we use to map values into the larger dataframe
small = pd.DataFrame({'is_even': [True, False], 'score': [10, 200]})
small
is_even score
0 True 10
1 False 200
这里的目标是使用条件语句将big 中的每一行与small 中的一行相匹配。假设small 的构造使得big 中的每一行总是有一个匹配,并且只有一个匹配。 (如果small 中必须有多行匹配,只需选择第一行。)
所需的输出类似于:
desired = pd.DataFrame({'match_1': [11, 12, 51, 52], 'metric': [200, 10, 200, 10]})
desired
match_1 metric
0 11 200
1 12 10
2 51 200
3 52 10
我很确定语法看起来类似于:
big['score'] = small.loc[small['is_even'] == ( (big['match_1'] / 2) == 0), 'score']
这行不通,因为small['is_even'] 是长度为 2 的系列,而 ( (big['match_1'] / 2) == 0) 是长度为 4 的系列。我要做的是,对于big 中的每一行,在small 中找到基于条件匹配的一行。
如果我可以得到一个序列,其中包含small 中与big 中的每一行匹配的正确行,那么我可以执行以下操作:
`big['score'] = small.loc[matching_rows, 'score']
我的问题是:如何生成序列matching rows?
(我认为)不是我想要的东西:
如果big 和small 中的列仅匹配常量值,则可以直接使用big.merge() 或big.groupby(),但是,在我的情况下,映射可以是任意复杂的布尔条件,例如:
(big['val1'] > small['threshold']) & (big['val2'] == small['val2']) & (big['val3'] > small['min_val']) & (big['val3'] < small['max_val'])
依赖isin()、any()等的解决方案是行不通的,因为条件检查可以任意复杂。
我当然可以将apply() 的函数创建到更大的 DataFrame,但同样,我很确定有一个更简单的解决方案。
答案可能归结为“计算一些中间列,直到你可以进行简单的合并”或“只使用apply(),但我可以发誓,有一种方法可以做我上面描述的事情。
【问题讨论】:
-
数据框是否在数据库中派生?如果是这样,您的条件匹配(一对多)可以在 SQL 中处理。 pandas 无需在内存中重组。