[英]Is it possible to conditionally combine data frame rows using pandas in python3?
[英]Pandas: conditionally matching rows in a smaller data frame
(更新:添加了desired
數據框)
首先我要說,我有足夠的信心相信幾年前我找到了解決該問題的方法,但是我仍無法找到該方法。
解決類似問題但不能解決我的特殊問題的問題包括:
假設我有一個正在處理許多列的數據框:
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()
,但我發誓有一種方法可以執行上述操作。
一種方法是使用merge
,其中on_left
不是列,而是鍵的向量。 通過將small
的索引設置為is_even
它變得更簡單:
>>> small.set_index('is_even', inplace=True)
>>> condition = big['match_1'] % 2 == 0
>>> pd.merge(big, small, left_on=condition, right_index=True, how='left')
match_1 score
0 11 200
1 12 10
2 51 200
3 52 10
您可以使用True和False索引small
索引,並直接.ix
查找。 不確定它是否比中間列/合並還要整齊:
In [127]: big = pd.DataFrame({'match_1': [11, 12, 51, 52]})
In [128]: small = pd.DataFrame({'score': [10, 200]}, index=[True, False])
In [129]: big['score'] = small.ix[pd.Index(list(big.match_1 % 2 == 0))].score.values
In [130]: big
Out[130]:
match_1 score
0 11 200
1 12 10
2 51 200
3 52 10
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.