【问题标题】:How to check if values of column 1 in dataframe B are between the values of column 1 and 2 in dataframe A. If true, return column 2 of dataframe A如何检查数据框 B 中第 1 列的值是否介于数据框 A 中第 1 列和第 2 列的值之间。如果为真,则返回数据框 A 的第 2 列
【发布时间】:2019-04-25 13:10:46
【问题描述】:

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

我想将dataframe A的ID_position列添加到dataframe B,所以我知道哪个RSSI值(dataframe B)对应哪个ID_position(dataframe 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)

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

提前谢谢你!

【问题讨论】:

  • 您能否也添加您添加的小数据帧的预期输出?
  • @Efran 我添加了数据框 B 的预期结果

标签: python pandas dataframe merge localization


【解决方案1】:

您可以使用ID_user 上的两个数据框执行outer merge,这会返回一个many-to-many 产品(所以这些都是组合,例如笛卡尔产品)。

然后我们在start_time &lt; timestamp &lt; 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

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

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

【讨论】:

  • 感谢您的代码。不幸的是,有 277 个位置,当找到位置 1 的每个时间戳时,代码就会停止。数据集非常大,所以我当然必须以较小的部分运行它。
  • 不确定你的意思,也许编辑你的示例数据,这样它就会发现这个问题@user11410373
  • 总共有277个职位。数据框 B 比数据框 A 大得多,因此许多 RSSI 值将归因于一个位置。我更新了预期结果,如您所见,在第 1809 行开始位置 2。很抱歉,我一开始不清楚。 @尔凡
  • 使用您的新数据框 @user11410373 运行此程序时,我仍然得到正确的结果。请参阅我编辑的答案。最后一个数据框与您的预期结果相同
  • 非常感谢!重新启动 Python @Erfan 后似乎可以正常工作
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-19
  • 2015-11-30
  • 2016-04-15
  • 2023-02-22
  • 2019-09-12
相关资源
最近更新 更多