簡體   English   中英

熊貓:有條件地匹配較小數據框中的行

[英]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


(我認為)不是我想要的東西:

如果bigsmall中的列僅在常量值上匹配,這將是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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM