Я пытаюсь соединить фрагмент фрейма данных с другим. Структура присоединяемого фрейма данных упрощена ниже:
left:
ID f1 TIME
1 10 1
3 10 1
7 10 1
9 10 2
2 10 2
1 10 2
3 10 2
right:
ID f2 f3
1 0 11
7 9 11
Мне нужно выбрать левый набор данных по времени, и мне нужно прикрепить правый, результат, который я хотел бы получить, будет следующим:
left:
ID f1 TIME f2 f3
1 10 1 0 11
3 10 1 nan nan
7 10 1 9 11
9 10 2 nan nan
2 10 2 nan nan
1 10 2 nan nan
3 10 2 nan nan
В настоящее время я обычно присоединяюсь к фреймам данных следующим образом:
left = left.join(right.set_index('ID'), on='ID')
В этом случае я использую:
left[left.TIME == 1] = left[left.TIME == 1].join(right.set_index('ID'), on='ID')
Я также пробовал слияние, но результат - левый фрейм данных без каких-либо других столбцов. Наконец, структура моего скрипта должна делать это для каждого уникального ВРЕМЕНИ в фрейме данных, таким образом:
for t in numpy.unique(left.TIME):
#do join on the fragment left.TIME == t
Если я сохраню возвращаемое значение из функции соединения в новом фрейме данных, все будет работать нормально, но попытка добавить значение в левый фрейм данных не сработает.
Обновлено: идентификаторы левого набора данных могут присутствовать несколько раз, но не внутри одного и того же значения TIME.
🤔 А знаете ли вы, что...
Python популярен в анализе данных и машинном обучении с помощью библиотеки scikit-learn.
Это один способ:
res = left.drop_duplicates('ID')\
.merge(right, how='left')\
.append(left[left.duplicated(subset=['ID'])])
# ID TIME f1 f2 f3
# 0 1 1 10 0.0 11.0
# 1 3 1 10 NaN NaN
# 2 7 1 10 9.0 11.0
# 3 9 2 10 NaN NaN
# 4 2 2 10 NaN NaN
# 5 1 2 10 NaN NaN
# 6 3 2 10 NaN NaN
Обратите внимание, что столбцы f2
и f3
становятся float
, поскольку NaN
считается плавающим.
Вы можете фильтровать сначала по boolean indexing
, merge
и concat
в последнюю очередь:
df1 = left[left['TIME']==1]
#alternative
#df1 = left.query('TIME == 1')
df2 = left[left['TIME']!=1]
#alternative
#df2 = left.query('TIME != 1')
df = pd.concat([df1.merge(right, how='left'), df2])
print (df)
ID TIME f1 f2 f3
0 1 1 10 0.0 11.0
1 3 1 10 NaN NaN
2 7 1 10 9.0 11.0
3 9 2 10 NaN NaN
4 2 2 10 NaN NaN
5 1 2 10 NaN NaN
6 3 2 10 NaN NaN
Обновлено: merge
создает индексы по умолчанию, поэтому возможное решение - сначала создать столбец, а затем установить индекс:
print (left)
ID f1 TIME
10 1 10 1
11 3 10 1
12 7 10 1
13 9 10 2
14 2 10 2
15 1 10 2
16 3 10 2
#df = left.merge(right, how='left')
df1 = left[left['TIME']==1]
df2 = left[left['TIME']!=1]
df = pd.concat([df1.reset_index().merge(right, how='left').set_index('index'), df2])
print (df)
ID TIME f1 f2 f3
10 1 1 10 0.0 11.0
11 3 1 10 NaN NaN
12 7 1 10 9.0 11.0
13 9 2 10 NaN NaN
14 2 2 10 NaN NaN
15 1 2 10 NaN NaN
16 3 2 10 NaN NaN
Обновлено:
После обсуждения после изменения входных данных возможно использование:
df = left.merge(right, how='left', on=['ID','TIME'])