#python #pandas #bernoulli-probability
#python #pandas #бернулли-вероятность
Вопрос:
У меня есть фрейм данных, где каждая строка содержит список строк. Я написал функцию, которая выполняет испытание типа Бернулли для каждой строки, где с некоторой вероятностью (здесь 0,5) каждое слово удаляется, если испытание прошло успешно. Смотрите ниже:
import numpy as np
import pandas as pd
def bernoulli_trial (sublist, prob = 0.5):
# create mask of trial outcomes per each object in sublist
mask = np.random.binomial(n=1, p=prob, size=len(sublist))
# perform transformation on bernoulli successes
transformed_sublist = [token for delete, token in zip(mask, sublist) if not delete]
return transformed_sublist
Это работает, как и ожидалось, когда я передаю каждую строку фрейма данных, согласно:
df = pd.DataFrame(data={'store': [1,2,3], 'colours': [['red','blue','yellow','green','brown','pink'],
['black','white'],
['purple','orange','cyan','mauve']]})
df['colours'] = df['colours'].apply(bernoulli_trial)
Out:
0 [red, green]
1 [black]
2 [orange, cyan]
Name: colours, dtype: object
Однако вместо того, чтобы применять функцию равномерно по каждому подсписку и для каждой строки, я теперь хочу применить условия для (а) будет ли данный подсписок передан функции (да / нет), и (б) какие строки в этом подсписке будут применены (т. Е. С помощьюуказав, что я хочу тестировать только определенные цвета).
Я думаю, что у меня есть рабочее решение для части (a) — путем обертывания функции Бернулли внутри функции, которая проверяет, выполнено ли заданное условие (т. Е. Длина подсписка больше 2 объектов?) — это работает (см. Ниже), но я не уверен, есть ли более эффективный (подробнее pythonic) способ сделать это.
def sublist_condition_check(sublist):
if len(sublist) > 2:
sublist = bernoulli_trial(sublist)
else:
sublist = sublist
return sublist
Обратите внимание, что любые подсписки, которые не соответствуют условию, должны оставаться неизменными.
df['colours'].apply(sublist_condition_check)
Out:
0 [red, brown]
1 [black, white] # this sublist had only two elements so remains unchanged
2 [mauve]
Name: colours, dtype: object
Тем не менее, я полностью зациклен на том, как применять условную логику к каждому слову. Скажем, например, я хотел применить пробную версию только к заранее заданному списку цветов [‘red’, ‘mauve’,’black’] — при условии прохождения проверки состояния подсписка — как я мог это сделать?
Псевдокод для того, чего я надеюсь достичь, будет примерно следующим:
for sublist in df:
if len(sublist) > 2: # check if sublist contains more than two objects
for colour in sublist: # cycle through each colour within the sublist
if colour in ['red','mauve','black']:
colour = bernoulli_trial (colour) # only run bernoulli if colour in list
else:
colour = colour # if colour not in list, colour remains unchanged
else:
sublist = sublist # if sublist <= 2, sublist remains unchanged
Я знаю, что буквальная интерпретация этого не сработает, поскольку начальная функция bernoulli_trial получает список, а не отдельную строку. Но, надеюсь, это описывает то, чего я хочу достичь.
Ответ №1:
Не уверен в этикете, касающемся ответа на мой собственный вопрос, но подумал, что я бы предоставил некоторые подробности рабочего решения, которое я определил, на случай, если кто-нибудь столкнется с подобной ситуацией.
Я расширил начальную функцию Бернулли, включив в нее дополнительный оператор if в зависимости от того, соответствует ли каждая строка критериям включения.
# internal function - bernoulli trial for each string in sublist
def bernoulli_trial (sublist, prob = 0.50):
# set token criteria for performing bernoulli trial
token_criteria = ['red','black','purple'] # perform trial only on these strings
# create mask of trial outcomes per each word in sublist
mask = np.random.binomial(n=1, p=prob, size=len(turn))
# perform transformation (deletion) on bernoulli successes
transformed_turn = []
for token, delete in zip(turn, mask):
if token not in token_criteria:
transformed_turn.append(token)
else:
if delete == 0: # retain only those strings not marked for deletion
transformed_turn.append(token)
return transformed_sublist
В сочетании с sublist_condition_check
функцией, описанной в вопросе, это теперь работает так, как ожидалось