pandas: найти наименьший диапазон в df1, который включает в себя значение в df2 с учетом пользовательского pd.series s, диапазоны в df1, выровненные по s, и значение в df2 - PullRequest
0 голосов
/ 03 апреля 2020

У меня есть серия alphanumeri c с непоследовательным началом и концом.

s = pd.Series(['A0',1', '2', '3', '5', '7', '11', '12', '15', '1A', '1C', '1V', 'A1', 'A5', 'B7', 'C8', '99'])

У меня есть первый кадр данных, df1, который содержит начало и конец диапазона указанной последовательности. Диапазон включает в себя вырезать и всю последовательность.

data = {'group':['NJ', 'NJ', 'NJ', 'NY', 'NY', 'NY'], 'Start':['A0','11', '1A', 'A0', '7', '1V'], 'End':['99', 'A5', 'A1', '99', '15', 'B7']}
df1 = pd.DataFrame(data)

Второй кадр данных df2 содержит группу, одно из этих значений и другие атрибуты.

data2={'group': ['NJ', 'NY'], 'value':['1C', 'A5']}
df2 = pd.DataFrame(data2)

Вот что я хочу получить:

data3 = {'group': ['NJ','NY'], 'value':['1C', 'A5'], 'range':['1A-A1', '1V-B7']}
new_df2 = pd.DataFrame(data3)

Если значение присутствует в нескольких диапазонах в определенной группе, мне нужен наименьший диапазон.

Вот то, что я пробовал. Сначала я добавил новый столбец к df1, чтобы указать длину диапазона:

s = s.to_frame().rename(columns = {0:'value'})
def range_len(row):
    a = s[s['value'] == row['Start']].index[0]
    b = s[s['value'] == row['End']].index[0]
    d = b - a
    return d

df1['range_length'] = df1.apply(lambda row: range_len(row), axis = 1)

Затем я могу использовать длину сортировки при поиске диапазона, чтобы определить кратчайший диапазон. Я попытался пройтись по отдельным образцам, выбрав конкретные c примеров, и я смог получить желаемый результат для значения.

k = df1[df1['group'] == 'NJ'].sort_values(by = 'range_length')
k['new'] = ['1C' in s.loc[f : t].values for f, t in zip(list(k['Start']), list(k['End']))]
i = k[k.new == True].iloc[0]
str(list(i[['Start', 'End']]))

Однако, когда я пытаюсь собрать его в функцию и применить к df, в результате я получаю NaN. без попытки / кроме я получаю TypeErrors.

def get_range(row):
    temp_df = df1[df1['group'] == row['group']].sort_values(by = 'range_length')
    try:
        temp_df['new'] = [df2['value'] in s.loc[f : t].values for f, t in zip(list(temp_df['Start']), list(temp_df['End']))]
        s = df[df.new == True].iloc[0]
        r = str(list(s[['Start', 'End']]))
        return r
    except:
        return 'not found'
df2['range'] = df2.apply(lambda row: get_range(row), axis = 1)

Это игрушечный пример. Мне нужно использовать серию длиной ~ 30 000, df1 с 2 миллионами строк и df2 с> 10 миллионами строк. Я новичок в python / pandas, и это, вероятно, неуклюже. Советы по решению проблемы и повышению производительности приветствуются.

...