#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()]