首页 > 解决方案 > 如何检查数据框 B 中第 1 列的值是否介于数据框 A 中第 1 列和第 2 列的值之间。如果为真,则返回数据框 A 的第 2 列

问题描述

我有两个数据框。数据框 A 有五列:start_time、end_time、ID_user、ID_position 和orientation。Dataframe B 有四列:timestamp、ID_user、ID_sender 和 RSSI。

我想将数据帧A的ID_position列添加到数据帧B,所以我知道哪个RSSI值(数据帧B)对应于哪个ID_position(数据帧A)。为此,我需要知道某人在何时何地。所以我需要检查时间戳位于哪个 start_time 和哪个 end_time (数据帧 A)之间(数据帧 B)。总共有277个职位。

简单来说:如果时间戳(数据帧 B)在开始时间和结束时间(数据帧 A)之间,则将 ID_position 返回到相应的时间戳,并将其作为列添加到数据帧 B。

我在许多网站上搜索并尝试了很多东西,但这可能是我想出的最好的:我将列更改为 tolist() 因为列表的处理速度比列快。我尝试在函数中使用 for 循环来检查开始时间和时间戳并进行比较。我没有使用开始时间和结束时间,而是尝试只使用开始,因为这会减少 for 循环(但使用结束时间更好)。我尝试了合并、分配等,但无法弄清楚。我最有希望的解决方案放在下面。第一个解决方案导致一个时间戳的 ID_positions 列表,而不是一个位置。

def position (timestamp):
    pos_list = []
    pos = survey.ID_position
    time = 1540648136288
    for t in range(len(timestamp)):
        if (timestamp[t] <= time):
            pos_list.append(pos)
        elif (timestamp[t] > time):
            time = time + 8000
            pos = survey.ID_position + 1
    return(pos_list)


def numbers2 (position):
    pos_ID = []
    post_list = []
    for i in range(len(position)):
        pos_ID.append(position[i])
    def num_pos2(timestamp):
        pos_list = []
        pos = ID
        time = 1540648127883
        for t in range(len(timestamp)):
            if (time <= timestamp[t] <= (time+8000)):
                pos_list.append(pos[i])
            if timestamp[t] > time:
                pos_list.append(pos[i+1])
                time = time + 8000
                position = pos[i+1]
    return(pos_list)

Dataframe A(前几行,1108行×5列,共277个位置)

    start_time      end_time        ID_user ID_position orientation
0   1540648127883   1540648129883   1        1           1
1   1540648129884   1540648131883   1        1           2
2   1540648131884   1540648133883   1        1           3
3   1540648133884   1540648136288   1        1           4
4   1540648179559   1540648181559   1        2           1
5   1540648181560   1540648183559   1        2           2
6   1540648183560   1540648185559   1        2           3
7   1540648185560   1540648187846   1        2           4
8   1540648192618   1540648194618   1        3           1
9   1540648194619   1540648196618   1        3           2
10  1540648196619   1540648198618   1        3           3
11  1540648198619   1540648201336   1        3           4 

数据框 B(前几行,209393 行 × 4 列)

timestamp       ID_user ID_sender   RSSI
0   1540648127974   1   1080       -95
1   1540648128037   1   1          -51
2   1540648128076   1   1080       -95
3   1540648128162   1   1          -53
4   1540648128177   1   1080       -95

预期结果数据框 B:

timestamp       ID_user ID_sender   RSSI   ID_position
0   1540648127974   1   1080       -95     1
1   1540648128037   1   1          -51     1
2   1540648128076   1   1080       -95     1
3   1540648128162   1   1          -53     1
4   1540648128177   1   1080       -95     1
.......................... < a lot of rows between >
1809    1540648179571   1   1080    -75    2
1810    1540648179579   1   1       -55    2 
1811    1540648179592   1   1070    -96    2
1812    1540648179627   1   1069    -100   2
1813    1540648179669   1   1080    -78    2
1814    1540648179772   1   1080    -79    2

总数据集可以在:http ://wnlab.isti.cnr.it/localization

我想检查数据帧 B 的时间戳在哪个开始时间和结束时间(数据帧 A)之间,并且我想返回数据帧 A 的 ID_position。所以最后,数据帧 B 有一列 ID_positions 对应于正确的时间戳。例如:如果开始时间为 1,结束时间为 4,并且 ID_position 为 1。我想为时间戳 3 获取 ID_position 1,因为它介于 1 和 4 之间。

先感谢您!

标签: pythonpandasdataframemergelocalization

解决方案


您可以outer merge使用两个数据框来ID_user返回many-to-many产品(因此这些都是组合,例如笛卡尔积)。

query然后我们用on过滤start_time < timestamp < end_time

df = pd.merge(dfB, dfA, on='ID_user', how='outer')\
       .query('start_time < timestamp < end_time')\
       .drop(['start_time', 'end_time', 'orientation'], axis=1)\
       .reset_index(drop=True)

输出

print(df)
       timestamp  ID_user  ID_sender  RSSI  ID_position
0  1540648127974        1       1080   -95            1
1  1540648128037        1          1   -51            1
2  1540648128076        1       1080   -95            1
3  1540648128162        1          1   -53            1
4  1540648128177        1       1080   -95            1

请注意,我没有在<运算符中使用包含。<=如果需要,您可以将其更改为。

note2如果您的数据框很大。这将消耗内存,请参阅many-to-many上面的解释。

在 OP 对多个职位发表评论后进行编辑

我仍然得到正确的结果。

# Print the new used dataframes
print(dfA, '\n')
print(dfB, '\n')

       start_time       end_time  ID_user  ID_position  orientation
0   1540648127883  1540648129883        1            1            1
1   1540648129884  1540648131883        1            1            2
2   1540648131884  1540648133883        1            1            3
3   1540648133884  1540648136288        1            1            4
4   1540648179559  1540648181559        1            2            1
5   1540648181560  1540648183559        1            2            2
6   1540648183560  1540648185559        1            2            3
7   1540648185560  1540648187846        1            2            4
8   1540648192618  1540648194618        1            3            1
9   1540648194619  1540648196618        1            3            2
10  1540648196619  1540648198618        1            3            3
11  1540648198619  1540648201336        1            3            4 

        timestamp  ID_user  ID_sender  RSSI
0   1540648127974        1       1080   -95
1   1540648128037        1          1   -51
2   1540648128076        1       1080   -95
3   1540648128162        1          1   -53
4   1540648128177        1       1080   -95
5   1540648179571        1       1080   -75
6   1540648179579        1          1   -55
7   1540648179592        1       1070   -96
8   1540648179627        1       1069  -100
9   1540648179669        1       1080   -78
10  1540648179772        1       1080   -79 

df = pd.merge(dfB, dfA, on='ID_user', how='outer')\
       .query('start_time < timestamp < end_time')\
       .drop(['start_time', 'end_time', 'orientation'], axis=1)\
       .reset_index(drop=True)

print(df)
        timestamp  ID_user  ID_sender  RSSI  ID_position
0   1540648127974        1       1080   -95            1
1   1540648128037        1          1   -51            1
2   1540648128076        1       1080   -95            1
3   1540648128162        1          1   -53            1
4   1540648128177        1       1080   -95            1
5   1540648179571        1       1080   -75            2
6   1540648179579        1          1   -55            2
7   1540648179592        1       1070   -96            2
8   1540648179627        1       1069  -100            2
9   1540648179669        1       1080   -78            2
10  1540648179772        1       1080   -79            2

推荐阅读