簡體   English   中英

根據另一個 dataframe 中的行查詢一個 dataframe 行並比較值

[英]Query for one dataframe row based on row in another dataframe & compare values

所以我有兩個數據框。 第一個數據幀包含用於“評分”的數字數據,第二個數據幀包含模擬數據。

df1 = 基本記錄

df2 = 模擬記錄

第 1 部分:我要完成的是查詢 df1“基本記錄”以找到與 df2“模擬記錄”中“名稱”和“時間”列完全匹配的時間戳最近的行。

第 2 部分:然后我想使用 if then function 來確定模擬記錄行中的值是否落在使用基本記錄行中的兩個值創建的范圍之間,並返回 boolean。

低范圍 = df1['Po']-df1['Ref']

高范圍 = df1['Po']+df1['Ref']

如果 df2['Sim'] 介於其最近的 df1 基本記錄的低范圍和高范圍之間,那么我想在新列“Sim Score”中返回 true,否則返回 false

第 3 部分:我想為模擬記錄中的每一行重復第 1 部分和第 2 部分。

有用的信息:

  • df1(基本記錄)的行數比 df2(模擬記錄)多或少
  • df1 比 df2 有更多的列
  • df1 中的某些列具有相同的名稱,但 df2 中的值不同
  • 理想情況下,希望能夠對兩個數據幀進行切片,如果然后 function 只看到比較中使用的兩行
  • 只需要最近的 df1 基本記錄與 df2 模擬記錄進行比較
  • 以前在谷歌表格中使用 if then & 查詢組合公式將整個表格拖下(想用 python 和 pandas 替換)
df1 base records example (columns that matter)

Timestamp            Name     Time     Po  Ref

7/11/2022 11:30:00   trial   20 mins   5   2

7/10/2022 04:00:00   trial   20 mins   4   4

7/09/2022 02:45:00   trial   20 mins   2   2

6/28/2022 03:45:00   trial   20 mins   3   6
df2 simulation records example (columns that matter)

Timestamp             Name     Time     Sim

7/10/2022 05:15:00    trial   20 mins   7

7/11/2022 12:45:00    trial   20 mins   4

7/12/2022 03:30:00    trial   20 mins   8
desired result of new column added to df2

Timestamp             Name     Time     Sim  Sim Score

7/10/2022 05:15:00    trial   20 mins   7    True

7/11/2022 12:45:00    trial   20 mins   4    True

7/12/2022 03:30:00    trial   20 mins   8    False

因為您不提供構建 dataframe 的代碼,所以我將繪制一個潛在的解決方案:

首先,我假設您每天只有一個時間戳(在您的示例中看起來像這樣)。 因此,我會截斷或拆分時間戳,使其僅在一列中包含日期。 這樣做是為了我們可以根據日期加入數據幀,即對兩個數據幀使用set_index("date_column") (使用內部連接僅保留兩個數據幀中存在日期的行)。 最后,您可以使用apply()檢查您的情況:

df_joined['Sim Score'] = df_joined.apply(lambda row: (row['Po']-row['Ref'] <= row['Sim']) and (row['Po']+row['Ref'] >= row['Sim']), axis = 1)

使用pandas.DataFrame.reindex ,它的method提供最近找到可計算索引(例如,字符串不能計算距離)

或者使用merge_asof ,它的direction提供最近的





方法一:

reindex() with method='nearest'

df1['Timestamp'] = pd.to_datetime(df1['Timestamp'])
df1.set_index('Timestamp', inplace=True)
df1['l_r'] = df1['Po'] - df1['Ref']
df1['h_r'] = df1['Po'] + df1['Ref']
print(df1)
###
                      Name     Time  Po  Ref  l_r  h_r
Timestamp                                             
2022-07-11 11:30:00  trial  20 mins   5    2    3    7
2022-07-10 04:00:00  trial  20 mins   4    4    0    8
2022-07-09 02:45:00  trial  20 mins   2    2    0    4
2022-06-28 03:45:00  trial  20 mins   3    6   -3    9
df2['Timestamp'] = pd.to_datetime(df2['Timestamp'])
df2.set_index('Timestamp', inplace=True)
print(df2)
###
                      Name     Time  Sim
Timestamp                               
2022-07-10 05:15:00  trial  20 mins    7
2022-07-11 12:45:00  trial  20 mins    4
2022-07-12 03:30:00  trial  20 mins    8
temp = df2.join(df1.reindex(df2.index, method='nearest'), lsuffix='_left', rsuffix='_right')
print(temp)

在此處輸入圖像描述

如您所見,這是df2.join(df1)

一次按索引連接多個 DataFrame 對象。

使用method='nearest' ,在這種情況下,它將通過最近的Timestamp索引加入df2df1


df2['Sim Score'] = temp['Sim'].between(temp['l_r'], temp['h_r']).values
df2.reset_index(inplace=True)
print(df2)
###
            Timestamp   Name     Time  Sim  Sim Score
0 2022-07-10 05:15:00  trial  20 mins    7       True
1 2022-07-11 12:45:00  trial  20 mins    4       True
2 2022-07-12 03:30:00  trial  20 mins    8      False




方法二:

merge_asof() with direction='nearest'這種方式不會使用索引值執行,因此我們不必將列Timestamp設置為索引。 但它需要對綁定對象(在這種情況下我們合並列Timestamp )進行排序。

df1['Timestamp'] = pd.to_datetime(df1['Timestamp'])
# df1.set_index('Timestamp', inplace=True)
df1['l_r'] = df1['Po'] - df1['Ref']
df1['h_r'] = df1['Po'] + df1['Ref']
df1.sort_values(by='Timestamp', inplace=True)
print(df1)
###
            Timestamp   Name     Time  Po  Ref  l_r  h_r
3 2022-06-28 03:45:00  trial  20 mins   3    6   -3    9
2 2022-07-09 02:45:00  trial  20 mins   2    2    0    4
1 2022-07-10 04:00:00  trial  20 mins   4    4    0    8
0 2022-07-11 11:30:00  trial  20 mins   5    2    3    7
df2['Timestamp'] = pd.to_datetime(df2['Timestamp'])
# df2.set_index('Timestamp', inplace=True)
df2.sort_values(by='Timestamp', inplace=True)
print(df2)
###
            Timestamp   Name     Time  Sim
0 2022-07-10 05:15:00  trial  20 mins    7
1 2022-07-11 12:45:00  trial  20 mins    4
2 2022-07-12 03:30:00  trial  20 mins    8

temp = pd.merge_asof(df2 ,df1[['Timestamp', 'l_r', 'h_r']], on='Timestamp', direction='nearest')
print(temp)

在此處輸入圖像描述 如您所見,這是pd.merge_asof(df2, df1)

這類似於左連接,除了我們匹配最近的鍵而不是相等的鍵。 兩個 DataFrame 都必須按 key 排序。

對於左側 DataFrame 中的每一行:

“最近”搜索選擇右側 DataFrame 中的行,其“開”鍵與左側鍵的絕對距離最近。

df2['Sim Score'] = temp['Sim'].between(temp['l_r'], temp['h_r']).values
print(df2)
###
            Timestamp   Name     Time  Sim  Sim Score
0 2022-07-10 05:15:00  trial  20 mins    7       True
1 2022-07-11 12:45:00  trial  20 mins    4       True
2 2022-07-12 03:30:00  trial  20 mins    8      False

坦率地說,如果你有一個大數據集,處理索引的東西會更快。




方法2(在多個鍵上)

我重新修改了df1添加了不同的名稱和時間

df1 = pd.DataFrame({'Timestamp':['7/11/2022 11:30:00','7/11/2022 11:30:00','7/10/2022 04:00:00','7/10/2022 04:00:00','7/09/2022 02:45:00','6/28/2022 03:45:00'],
                    'Name':['trial','trial','trial','non-trial','trial','trial'],
                    'Time':['20 mins','30 mins','20 mins','20 mins','20 mins','20 mins'],
                    'Po':[5, 6, 4, 1, 2, 3],
                    'Ref':[2, 2, 4, 3, 2, 6]})
df1['Timestamp'] = pd.to_datetime(df1['Timestamp'])
df1['l_r'] = df1['Po'] - df1['Ref']
df1['h_r'] = df1['Po'] + df1['Ref']
df1.sort_values(by='Timestamp', inplace=True)
print(df1)
###
            Timestamp       Name     Time  Po  Ref  l_r  h_r
5 2022-06-28 03:45:00      trial  20 mins   3    6   -3    9
4 2022-07-09 02:45:00      trial  20 mins   2    2    0    4
2 2022-07-10 04:00:00      trial  20 mins   4    4    0    8
3 2022-07-10 04:00:00  non-trial  20 mins   1    3   -2    4
0 2022-07-11 11:30:00      trial  20 mins   5    2    3    7
1 2022-07-11 11:30:00      trial  30 mins   6    2    4    8
print(df2)
###
            Timestamp   Name     Time  Sim
0 2022-07-10 05:15:00  trial  20 mins    7
1 2022-07-11 12:45:00  trial  20 mins    4
2 2022-07-12 03:30:00  trial  20 mins    8

重要的:

只能在單個鍵上 merge_asof,因此其他人會使用on=來處理。

temp = pd.merge_asof(df2, df1[['Timestamp', 'Name', 'Time', 'l_r', 'h_r']], on='Timestamp', by=['Name','Time'], direction='nearest')
print(temp)

在此處輸入圖像描述

df2['Sim Score'] = temp['Sim'].between(temp['l_r'], temp['h_r']).values
print(df2)
###
            Timestamp   Name     Time  Sim  Sim Score
0 2022-07-10 05:15:00  trial  20 mins    7       True
1 2022-07-11 12:45:00  trial  20 mins    4       True
2 2022-07-12 03:30:00  trial  20 mins    8      False

參考:
pandas.DataFrame.join
pandas.merge_asof

您可以通過pandasql來做到這一點:但請注意,您最好向其中一列添加唯一約束(例如,一些試驗)

from pandasql import sqldf

df3 = sqldf('''
    select df2.Timestamp, df2.Name, df2.Time, df2.Sim,
    
    case
        when Sim >= (df1.Po - df1.Ref) and Sim <= (df1.Po + df1.Ref) then 'True'
        when Sim < (df1.Po - df1.Ref) or Sim > (df1.Po + df1.Ref) then 'False'
    end as 'Sim Score'
    
    from df1, df2
    
    where df2.Name == df1.Name and df2.Time == df1.Time        
''')

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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