фрейм данных pandas повторяет значение ячейки, представляющее собой список, и сравнивает каждый элемент с другой ячейкой

#python-3.x #pandas #dataframe

Вопрос:

У меня есть фрейм данных с 2 столбцами — кортеж и список:

 df = t l  (1,2) [1,2,3,4,5,6]  (0,5) [1,4,9]  (0,4) [9,11]  

Я хочу добавить новый столбец «сколько элементов из l находится в диапазоне t». Так, например, здесь, если будет:

 df =counter t l  2 (1,2) [1,2,3,4,5,6]  2 (0,5) [1,4,9]  0 (0,4) [9,11]  

Каков наилучший способ сделать это?

Ответ №1:

Используйте понимание списка с генератором и sum :

 df['counter'] = [sum(a lt;= i lt;= b for i in y) for (a, b), y in df[['t','l']].to_numpy()]  

Немного более быстрое решение с set.intersection помощью is:

 df['counter'] = [len(set(range(a, b 1)).intersection(y))   for (a, b), y in df[['t','l']].to_numpy()]  print (df)  t l counter 0 (1, 2) [1, 2, 3, 4, 5, 6] 2 1 (0, 5) [1, 4, 9] 2 2 (0, 4) [9, 11] 0  

Производительность в тестовых данных:

 #30k rows df = pd.concat([df] * 10000, ignore_index=True)  In [67]: %timeit [sum(a lt;= i lt;= b for i in y) for (a, b), y in df[['t','l']].to_numpy()] 65.3 ms ± 1.22 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)  In [68]: %timeit [len(set(range(a, b 1)).intersection(y)) for (a, b), y in df[['t','l']].to_numpy()] 60.7 ms ± 520 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)  

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

1. @jezrael, А если я хочу взять фактические значения (вместо просто счетчика)?

2. @jezrael Метод с set.intersection для меня не работает, я получаю: ошибка типа: объект ‘float’ не может быть интерпретирован как целое число. сработало только первое решение.

3. @okuoub — Использовать df['counter'] = [[i for i in y if a lt;= i lt;= b] for (a, b), y in df[['t','l']].to_numpy()]