如何检查数据框B中的列1的值是否在数据框A中的列1和2的值之间。如果为true,则返回数据框A的列2

时间:2019-04-25 13:10:46

标签: python pandas dataframe merge localization

我有两个数据框。数据框A具有五列:开始时间,结束时间,ID_用户,ID_位置和方向。数据框B具有四列:时间戳,ID_user,ID_sender和RSSI。

我想将数据帧A的ID_position列添加到数据帧B,所以我知道哪个RSSI值(数据帧B)对应于哪个ID_position(数据帧A)。为此,我需要知道某人什么时候在哪里。因此,我需要检查时间戳位于哪个开始时间和结束时间(数据帧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)

数据框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之间。

提前谢谢!

1 个答案:

答案 0 :(得分:0)

您可以对ID_user上的两个数据帧执行outer merge,这将给您带来many-to-many乘积(所以这些都是组合,例如笛卡尔乘积)。

然后我们在start_time < timestamp < end_time上用query进行过滤:

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