Фреймы данных Pandas — поиск целого числа из одного фрейма данных в строковом столбце в другом фрейме данных

#python #pandas #dataframe

#python #pandas #фрейм данных

Вопрос:

У меня есть два фрейма данных:

DF1

                 cid          dt        tm    id    distance
2      ed032f716995  2021-01-22  16:42:48    43   21.420561
3      16e2fd96f9ca  2021-01-23  23:19:43   539  198.359355
102    cf092e68fa82  2021-01-22  09:03:14     8   39.599627
104    833ccf05433b  2021-01-24  02:53:08    11   33.168314
 

DF2

         id            cluster  
0        3                      
1        6             7,8,43  
2       20               1817  
3       25   
4       10  11,13,14,15,9,539 
 

Я хочу выполнить поиск каждого id df1 в cluster столбце df2 in . Желаемый результат:

                 cid          dt        tm    id    distance     cluster
2      ed032f716995  2021-01-22  16:42:48    43   21.420561     7,8,43
3      16e2fd96f9ca  2021-01-23  23:19:43   539  198.359355     11,13,14,15,9,539
102    cf092e68fa82  2021-01-22  09:03:14     8   39.599627     7,8,43 
104    833ccf05433b  2021-01-24  02:53:08    11   33.168314     11,13,14,15,9,539
 

В приведенной выше df1 — строке 1, поскольку 43 присутствует в df2, я включаю все сведения о кластере для df1 — строки 1.

Я попробовал следующее:

 for index, rows in df1.iterrows():
    for idx,rws in df2.iterrows():
        if (str(rows['id']) in str(rws['cluster'])):
            print([rows['id'],rws['cluster']])
 

Похоже, это работает. Однако, поскольку df2['cluster'] это строка, даже если есть частичное совпадение, она возвращает результат. Например, если df1 [‘id’] = 34, а df2 [‘cluster’] Имеет 344 432 и т. Д., Он все равно соответствует на основе 344 и возвращает положительный результат.

Я попробовал другой вариант из SO here:

 d = {k: set(v.split(',')) for k, v in df2.set_index('id')['cluster'].items()}
df1['idc'] = [next(iter([k for k, v in d.items() if set(x).issubset(v)]), '') for x in str(df1['id'])]
 

Однако в приведенном выше я получаю сообщение об ошибке, указывающее, что длина переменной отличается между двумя наборами данных.

Как мне сопоставить кластер на основе точного совпадения столбца id в df1?

Ответ №1:

Один из способов — разделить cluster , explode it и map:

 to_map = (df2.assign(cluster_i=df2.cluster.str.split(','))
    .explode('cluster_i').dropna()
    .set_index('cluster_i')['cluster']
)

df1['cluster'] = df1['id'].astype(str).map(to_map)
 

Вывод:

               cid          dt        tm   id    distance            cluster
2    ed032f716995  2021-01-22  16:42:48   43   21.420561             7,8,43
3    16e2fd96f9ca  2021-01-23  23:19:43  539  198.359355  11,13,14,15,9,539
102  cf092e68fa82  2021-01-22  09:03:14    8   39.599627             7,8,43
104  833ccf05433b  2021-01-24  02:53:08   11   33.168314  11,13,14,15,9,539
 

Комментарии:

1. Спасибо. Когда я использовал код, я получаю эту ошибку TypeError: explode() takes 1 positional argument but 2 were given

2. @Apricot это странно. какая у вас версия Pandas?

3. извините, мой плохой ….. код работает отлично…. У меня было слишком много сложностей в моем производственном наборе данных.