#python #excel #pandas #merge #timestamp
#python #excel #pandas #объединить #временная метка
Вопрос:
Пишу свою первую программу для организации некоторых данных, уже несколько месяцев занимаюсь python. Эта небольшая программа будет использоваться в ближайшем будущем с прототипом RFID-считывателя, который я разрабатываю. Я успешно взял .txt и . xls, извлек соответствующую информацию, теперь я хочу сопоставить их на основе метки времени в формате XX: XX: XX. .txt — это данные с моего GPS, .xls содержит информацию о тегах из RFID-меток.
Мне нужно только местоположение GPS в паре с идентификатором тега на основе ближайшей временной метки.
Пожалуйста, взгляните на то, что у меня есть на данный момент, и предоставьте любое направление или совет, который у вас может быть.
import numpy as np
import pandas as pd
import xlrd
filename_xls = '11_4_TAG.xls'
df = pd.read_excel(filename_xls)
tag_data=(df[['Time', 'TagID']])
#print(tag_data)
filename = '11_4_GPS.txt'
df_gps = pd.read_csv(filename, delimiter=r"s ", skiprows=17, skipfooter=3, engine='python', encoding="unicode_escape")
gps_data=(df_gps[['Latitude', 'Longitude', 'Time']])
#print(gps_data)
pd.merge_asof(tag_data, gps_data, on='Time', direction='nearest')
#print(pd.merge_asof)
Я перепробовал много вариантов «вкл», «направление» и «по»
Вот результаты для моих двух новых наборов данных:
tag_data
WARNING *** OLE2 inconsistency: SSCS size is 0 but SSAT size is non-zero
Time TagID
0 10:18:32 E280116060000207A633DAB6
1 10:18:57 A15427AABB00112233445566
2 10:19:07 E280116060000207A6336C96
3 10:19:09 E280116060000207A6341969
4 10:19:34 E280116060000207A633E5B9
5 10:19:40 E280116060000207A633A846
6 10:19:56 A94439112233445566778899
7 10:20:01 E200001D52120136069068C0
8 10:20:05 E280116060000207A633DA16
9 10:20:07 A63367112233445566778899
10 10:20:12 E280116060000207A633A836
11 10:20:15 E280116060000207A633CBD9
12 10:20:18 E200001D5212006106702126
13 10:20:20 A39223112233445566778899
14 10:20:28 E280116060000207A633DCC6
15 10:20:50 A02257AABB00112233445566
16 10:22:24 E280116060000207A633DA26
17 10:22:44 E280116060000207A6336AC6
18 10:23:43 E280116060000207A633DA46
19 10:24:03 E280116060000207A6336CA6
20 10:24:22 E280116060000207A633DC96
21 10:28:01 C10002AABB00112233445566
22 10:28:05 013193AABB00112233445566
23 10:28:12 017072AABB00112233445566
24 10:28:22 023764AABB00112233445566
25 10:28:42 A15800AABB00112233445566
26 10:28:49 E280116060000207A6336CC6
27 10:28:51 E280116060000207A6344236
28 10:29:00 E280116060000207A6336CB6
29 10:29:01 E280116060000207A633CBB9
30 10:29:08 E280116060000207A6341959
31 10:29:11 A72546AABB00112233445566
32 10:29:15 A93853112233445566778899
33 10:29:15 A93853AABB00112233445566
34 10:30:46 A13832AABB00112233445566
35 10:30:52 A02533AABB00112233445566
36 10:30:58 00111160600002078899CBA9
37 10:31:23 A83503AABB00112206906A73
[Finished in 0.8s]
gps_data
WARNING *** OLE2 inconsistency: SSCS size is 0 but SSAT size is non-zero
Latitude Longitude Time
0 N43°03.6205' W085°57.5513' 10:17:46
1 N43°03.6205' W085°57.5512' 10:17:49
2 N43°03.6203' W085°57.5514' 10:17:51
3 N43°03.6202' W085°57.5511' 10:17:54
4 N43°03.6199' W085°57.5518' 10:17:57
.. ... ... ...
342 N43°03.6162' W085°57.5477' 10:33:03
343 N43°03.6163' W085°57.5472' 10:33:06
344 N43°03.6168' W085°57.5477' 10:33:09
345 N43°03.6167' W085°57.5477' 10:33:11
346 N43°03.6163' W085°57.5486' 10:33:14
[347 rows x 3 columns]
[Finished in 0.8s]
Код ошибки:
WARNING *** OLE2 inconsistency: SSCS size is 0 but SSAT size is non-zero
Traceback (most recent call last):
File "C:UsersOwnerDocumentsSoftwarePython ProgramsData_parsedata_parse_xls.py", line 15, in <module>
pd.merge_asof(tag_data, gps_data, on='Time', direction='nearest')
File "C:UsersOwnerAppDataLocalPackagesPythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0LocalCachelocal-packagesPython38site-packagespandascorereshapemerge.py", line 563, in merge_asof
return op.get_result()
File "C:UsersOwnerAppDataLocalPackagesPythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0LocalCachelocal-packagesPython38site-packagespandascorereshapemerge.py", line 1483, in get_result
join_index, left_indexer, right_indexer = self._get_join_info()
File "C:UsersOwnerAppDataLocalPackagesPythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0LocalCachelocal-packagesPython38site-packagespandascorereshapemerge.py", line 884, in _get_join_info
(left_indexer, right_indexer) = self._get_join_indexers()
File "C:UsersOwnerAppDataLocalPackagesPythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0LocalCachelocal-packagesPython38site-packagespandascorereshapemerge.py", line 1789, in _get_join_indexers
return func(left_values, right_values, self.allow_exact_matches, tolerance)
File "pandas_libsjoin.pyx", line 966, in pandas._libs.join.__pyx_fused_cpdef
TypeError: No matching signature found
[Finished in 0.8s]
Комментарии:
1. Вы уверены, что хотите объединить вовремя? потому что это время должно точно совпадать для объединения
2. В настоящее время это единственные две точки данных, которые у меня есть общего между двумя электронными таблицами. Я собираю данные GPS, а также собираю данные тегов, прототип, который я разрабатываю, будет фиксировать информацию GPS во время чтения тега. Думаю, на этом этапе мне больше не понадобится это программное обеспечение. Читая «Pandas», они говорят о поиске ближайшего целого числа, я полагаю, что это может быть datetime, timestamp или intiger. Однако я не могу заставить его работать.
Ответ №1:
Как сказал @MhDG7, вы можете объединить только те значения, которые точно совпадают. Итак, ваша первая задача — для каждой временной метки в gps_data найти ближайшее совпадение между временными метками в tag_data. Ключевая строка ниже — это
tag_secs_for_gps_secs = [min(tag_data['Secs'], key = lambda tag_secs: abs(tag_secs - gps_secs)) for gps_secs in gps_data['Secs'] ]
это делает именно это. Здесь для каждого времени gps, выраженного в секундах (см. Ниже), мы находим элемент среди временных меток tag_data (также выраженных в секундах), который минимизирует абсолютное расстояние между двумя
Вот полный сценарий Сначала мы создаем игрушечные данные
import sys
import pandas as pd
from io import StringIO
from datetime import datetime
gps_data_raw = StringIO(
"""
Latitude,Longitude,Time
N43°03.6162',W085°57.5477',10:33:03
N43°03.6163',W085°57.5472',10:33:06
N43°03.6168',W085°57.5477',10:33:09
N43°03.6167',W085°57.5477',10:33:11
N43°03.6163',W085°57.5486',10:33:14
""")
gps_data = pd.read_csv(gps_data_raw)
tag_data_raw = StringIO(
"""
Time,TagID
10:33:01,C10002AABB00112233445566
10:33:05,013193AABB00112233445566
10:33:12,017072AABB00112233445566
10:33:22,023764AABB00112233445566
10:33:42,A15800AABB00112233445566
10:33:49,E280116060000207A6336CC6
10:33:51,E280116060000207A6344236
""")
tag_data = pd.read_csv(tag_data_raw)
Затем мы преобразуем временную метку в объект datetime и, в конечном итоге, в (целочисленные) секунды из base_date
base_date = datetime(1900, 1, 1, 0, 0, 0)
gps_data['Time'] = pd.to_datetime(gps_data['Time'], format='%H:%M:%S')
tag_data['Time'] = pd.to_datetime(tag_data['Time'], format='%H:%M:%S')
gps_data['Secs'] = gps_data['Time'].apply(lambda t: int((t-base_date).total_seconds()))
tag_data['Secs'] = tag_data['Time'].apply(lambda t: int((t-base_date).total_seconds()))
Затем мы сопоставляем временные метки, вставляем их в фрейм данных и объединяем в этом столбце
tag_secs_for_gps_secs = [min(tag_data['Secs'], key = lambda tag_secs: abs(tag_secs - gps_secs)) for gps_secs in gps_data['Secs'] ]
gps_data['Nearest_tag_secs'] = tag_secs_for_gps_secs
merged_data = gps_data.merge(tag_data, left_on = 'Nearest_tag_secs', right_on = 'Secs')
Фрейм данных resultimg merged_data
может потребовать небольшой очистки, но воспроизведен здесь полностью, чтобы вы могли видеть, что произошло
| | Latitude | Longitude | Time_x | Secs_x | Nearest_tag_secs | Time_y | TagID | Secs_y |
|---:|:-------------|:--------------|:--------------------|---------:|-------------------:|:--------------------|:-------------------------|---------:|
| 0 | N43°03.6162' | W085°57.5477' | 1900-01-01 10:33:03 | 37983 | 37981 | 1900-01-01 10:33:01 | C10002AABB00112233445566 | 37981 |
| 1 | N43°03.6163' | W085°57.5472' | 1900-01-01 10:33:06 | 37986 | 37985 | 1900-01-01 10:33:05 | 013193AABB00112233445566 | 37985 |
| 2 | N43°03.6168' | W085°57.5477' | 1900-01-01 10:33:09 | 37989 | 37992 | 1900-01-01 10:33:12 | 017072AABB00112233445566 | 37992 |
| 3 | N43°03.6167' | W085°57.5477' | 1900-01-01 10:33:11 | 37991 | 37992 | 1900-01-01 10:33:12 | 017072AABB00112233445566 | 37992 |
| 4 | N43°03.6163' | W085°57.5486' | 1900-01-01 10:33:14 | 37994 | 37992 | 1900-01-01 10:33:12 | 017072AABB00112233445566 | 37992 |
Комментарии:
1. Это большое спасибо. Сегодня я углублюсь в это и поиграю. Я понимаю, что вы оба сейчас говорите о слиянии по одному и тому же значению. Чтение происходит в течение нескольких минут, пока я обходил своих туристов и читал данные тегов. Мне также нужно будет сопоставить минуты, но я определенно вижу путь к тому, чтобы это произошло сейчас. Я никогда не понимал, насколько креативным нужно быть, чтобы писать код, получая от этого истинное удовольствие. Спасибо вам обоим.
2. нет проблем. Чтобы было ясно, что мой код соответствует общему количеству секунд с момента базовой даты (таким образом, уникальный номер для любой метки времени), а не только двум последним цифрам вашей метки времени
3. О, потрясающе, я безуспешно пытался преобразовать «временную метку» в какой-то intiger, рад видеть, что прошлой ночью я был на правильном пути. Я буду обновлять прогресс позже.
4. Спасибо, это отлично сработало! Я буду изучать / искать части этого кода в течение нескольких дней, чтобы полностью понять, но я получаю представление о том, что происходит с высоты птичьего полета. Я скопировал и вставил небольшое подмножество моих исходных данных, чтобы сначала все исправить, теперь я буду работать над тем, чтобы мои две электронные таблицы были заполнены в StringIO, как вы изобразили.
5. @Beasmazter,
SrtingIO
материал должен иметь только отдельный пример, который не зависит ни от каких файлов, и вам действительно не нужна эта часть в вашем окончательном решении. Вашаdf = pd.read_excel(filename_xls)
должна работать нормально (ну, вы можете следить за пробелами вокруг ваших значений, но кроме этого проблем быть не должно).