Пожалуйста, простите меня за название; Мне было трудно резюмировать сложный вопрос.
У меня есть фрейм данных pandas значений, который выглядит так:
col1 col2 col3 col4
10_Q999999 111_Q4987666 110_Q277778 111_Q999999
Скажем, порог равен 7. Мне нужно взять этот фрейм данных и удалить каждую ячейку, в которой любая из цифр после _Q падает ниже порогового значения 7. Для ячеек, где каждая цифра> = 7, я хочу сохранить только часть строки перед "_Q".
Желаемый результат будет выглядеть так:
col1 col2 col3 col4
10 111
Я пытаюсь найти способ разбить каждый столбец на «_Q», преобразовать последний фрагмент в список целых чисел, взять минимум, а затем сравнить минимум с порогом, наконец, удалив список целых чисел, но я ' m застрял посреди отвратительно вложенного списка:
[[[int(z) for z in y[-3:] if (z != '') and "Q" not in z ] for y in chunk[x].astype(str).str.split("_") if y != ''] for x in chunk[cols] if x != '']
Решение:
s=~chunk.apply(lambda x :
x.str.split('_Q').str[1].str.contains('[0:6]', na=False))
chunk = chunk.apply(lambda x : x.str.split('_Q').str[0])[s].fillna('')
Вы можете использовать split
с contains
s=~df.apply(lambda x : x.str.split('_Q').str[1].str.contains('1|2|3|4|5|6'))
df.apply(lambda x : x.str.split('_Q').str[0])[s].fillna('')
Out[549]:
col1 col2 col3 col4
0 10 111
Ты только что спас мне день. Огромное спасибо!
Мне действительно нужно было добавить аргумент для обработки na: na = False. Эта дама очень признательна за вашу помощь :)
Вы можете заменить 1|2|3|...
на [0-6]
.
Делаем переход с 1 | 2 | 3 | и т.д. до [0-x], предложенные @COLDSPEED, действительно увеличили скорость. Поскольку порог - это значение, вводимое пользователем, мне пришлось бы делать '| ".join для создания строки каждый раз, а вместо этого здесь просто используется форматирование строки для ввода порога. Большое спасибо!
Мне не нравится apply
, поэтому я предлагаю альтернативу, включающую stack
, str.split
и np.where
, для (надеюсь) лучшей производительности.
v = df.stack()
sp = v.str.split('_Q')
i, j = sp.str[0], sp.str[1]
v[:] = np.where(j.str.contains('[0-6]'), '', i)
v.unstack()
col1 col2 col3 col4
0 10 111
Спасибо за предложение. К сожалению, я показываю, что это немного медленнее, чем метод Вэня. применить: real 0m1.289s user 0m1.417s sys 0m3.403s stack: real 0m1.401s user 0m1.550s sys 0m3.524s
@SummerEla Хорошо, спасибо. Я думаю, проблема в стеке, он почти такой же медленный, как и apply. Надеюсь, они это исправят; есть большие возможности для улучшения ;-)
@SummerEla извините за недоразумение, проверьте обновление