Объедините два кадра данных на основе диапазонов, которые могут частично перекрываться с помощью панд, и отслеживайте несколько значений - PullRequest
0 голосов
/ 26 октября 2019

У меня есть два больших фрейма данных (100К строк), у одного есть «значения», у другого есть «типы». Я хочу назначить «тип» из df2 для столбца в df1 на основе глубины. Глубины указаны в столбцах «От» и «До». «Типы» также определяются глубиной «От» и «До». НО они НЕ одинаковые интервалы. Глубина df1 может охватывать несколько типов df2.

Я хочу назначить df2 'types' для df1, и, если есть несколько типов, попробуйте также захватить эту информацию. Пример ниже.

import pandas as pd
import numpy as np
df1=pd.DataFrame(np.array([[1,3,0.001],[3,5,0.005],[5,7,0.002],[7,10,0.001]]),columns=['From', 'To', 'val'])

df2=pd.DataFrame(np.array([[0.0,4,'A'],[4,5,'B'],[5,6,'C'],[6,8,'D'],[8,10,'E']]),columns=['From', 'To', 'Type'])

df1

Out[1]: 
   From    To    val
0   1.0   3.0  0.001
1   3.0   5.0  0.005
2   5.0   7.0  0.002
3   7.0  10.0  0.001

df2

Out[2]: 
  From  To Type
0    0   4    A
1    4   5    B
2    5   6    C
3    6   8    D
4    8  10    E

Возможный допустимый вывод:

Out[4]: 
  From  To    val                 Type
0    1   3  0.001                    A
1    3   5  0.005   1 unit A,2 units B
2    5   7  0.002    1 unit C,1 unit D
3    7  10  0.001  1 unit D, 3 units E

Процент типов также будет хорошим выводом в типе.

Одним из решений может быть созданиеновый фрейм данных с высоким разрешением «глубины» и прямое заполнение типов, а также выполнение своего рода VLOOKUP для «Кому» и «От».

Я также подумал о возможности создания столбца в каждом df, который является 'установить 'в зависимости от кол.

Возможно объединение или слияние, но сначала необходимо получить совместимые данные.

Не знаю, с чего начать. Надеюсь, что есть хороший способ справиться с этим, у меня в основном та же самая ситуация, что и у этого парня , но я не говорю на 'R' и хотел бы сообщить информацию о нескольких типах.

1 Ответ

1 голос
/ 26 октября 2019

С df2 создать вспомогательную Серию , отмечая каждую "начальную точку" единицы (диапазон длины 1 ):

units = df2.set_index('Type').apply(lambda row: pd.Series(
    range(row.From, row.To)), axis=1).stack()\
    .reset_index(level=1, drop=True)

Результат:

Type
A    0.0
A    1.0
A    2.0
A    3.0
B    4.0
C    5.0
D    6.0
D    7.0
E    8.0
E    9.0
dtype: float64

Затем определить функцию, генерирующую Тип для текущей строки:

def getType(row):
    gr = units[units.ge(row.From) & units.lt(row.To)].groupby(level=0)
    if gr.ngroups == 1:
        return gr.ngroup().index[0]
    txt = []
    for key, grp in gr:
        siz = grp.size
        un = 'unit' if siz == 1 else 'units'
        txt.append(f'{siz} {un} {key}')
    return ','.join(txt)

Ичтобы сгенерировать Тип столбец, примените его к каждой строке:

df1['Type'] = df1.apply(getType, axis=1)

Результат:

   From    To    val                Type
0   1.0   3.0  0.001                   A
1   3.0   5.0  0.005   1 unit A,1 unit B
2   5.0   7.0  0.002   1 unit C,1 unit D
3   7.0  10.0  0.001  1 unit D,2 units E

Этот результат немного отличается от ожидаемого результата,но я думаю, что вы создали его немного непоследовательным образом.

Я думаю, что мое решение является правильным (по крайней мере, более последовательным), потому что:

  1. Строка 1.0 - 3.0 полностью находится в пределах 0 4 A , поэтому результат просто A (как в вашем посте).
  2. Строка 3.0 -5.0 можно «разделить» на:
    • 3.0 - 4.0 в пределах 0 4 A (1 единица),
    • 4.0 - 5.0 находится в пределах 4 5 B ( также 1 единицу, но вы хотите 2 единицы здесь).
  3. Строка 5.0 - 7.0 может быть снова «разделена» на:
    • 5,0 - 6,0 находится в пределах 5 6 C ( 1 единица),
    • 6,0- 7,0 находится в пределах 6 8 D ( 1 , как и вы).
  4. Строка 7,0 - 10,0 можно «разделить» на:
    • 7,0 - 8,0 в пределах 6 8 D ( 1 единица, как и вы)
    • 8,0 - 10,0 находится в пределах 8 10 E ( 2 единиц, а не 3 как вы написали).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...