#python #pandas
#python #pandas
Вопрос:
Я пытаюсь воспроизвести оператор Case в моем скрипте python (с участием pandas), который применяется к фрейму данных и заполняет новый столбец в зависимости от того, как обрабатывается каждая строка, но кажется, что каждая строка попадает в условие else из-за того, что каждое значение в новом столбце является Other
. Моя первая мысль заключается в том, что это соответствует any()
условию, которое я использовал, но я чувствую, что могу использовать совершенно неправильный подход. Есть какие-либо рекомендации относительно направления, которое я должен предпринять?
Пример строк:
index | source_name
1 | CLICK TO CALL - New Mexico
2 | Las Vegas Community Partner
3 | Facebook - Test Camp - Los Angeles
4 | Google - Test Camp - Los Angeles
index | landing_page_url
1 | NaN
2 | https://lp.example.com/fb/la/test/
3 | https://lp.example.com/fb/la/test/?utm_source=facebook
4 | https://lp.example.com/google/la/test/?utm_source=google
Критерии кода:
# Criteria
fb_landing_page_crit = [
'utm_source=facebook',
'fbclid',
'test.com/fb/'
]
fb_source_crit = [
'fb',
'facebook'
]
google_landing_page_crit = [
'gclid'
]
google_source_crit = [
'click to call',
'discovery',
'call',
'website',
'landing page',
'display - lp'
]
local_listings_source_crit = [
'gmb'
]
partner_source_crit = [
'vegas community',
'new orleans community',
'dc community',
]
Условный:
def network_parse(df):
if isinstance(df, str):
if any(x in df['landing_page_url'] for x in fb_landing_page_crit):
return 'Facebook'
elif any(x in df['landing_page_url'] for x in google_landing_page_crit):
return 'Google'
elif any(x in df['source_name'] for x in fb_source_crit):
return 'Facebook'
elif any(x in df['source_name'] for x in google_source_crit):
return 'Google'
elif any(x in df['source_name'] for x in local_listings_source_crit):
return 'Local Listings'
elif any(x in df['source_name'] for x in partner_source_crit):
return 'Partner - Community Partnership'
else:
return 'Other'
else:
return 'Other'
Вызов функции:
df['network'] = df.apply(network_parse, axis=1) # Every row returns "Other"
Комментарии:
1. Похоже, что вы передаете серию в network_parse, а затем проверяете, является ли серия строкой. Это всегда будет false . В вашем обновленном решении вы вместо этого тестируете isinstance(df[‘landing_page_url’], str), который является строкой, если его NaN .
Ответ №1:
Я нашел лучший подход к проблеме. Вместо того, чтобы использовать методы contains, я решил запустить поиск по регулярным выражениям, чтобы узнать, найдены ли объединенные значения списка в строке столбца, и если они присутствуют, затем примените это значение. Ниже приведены мои обновления:
Списки:
fb_landing_page_crit = [
'utm_source=facebook',
'fbclid',
'test.com/fb/'
]
fb_landing_page_regex = "|".join(fb_landing_page_crit)
google_landing_page_crit = [
'gclid'
]
google_landing_page_regex = "|".join(google_landing_page_crit)
fb_source_crit = [
'fb',
'facebook'
]
fb_source_regex = "|".join(fb_source_crit)
google_source_crit = [
'click to call',
'discovery',
'call',
'website',
'landing page',
'display - lp'
]
google_source_regex = "|".join(google_source_crit)
local_listings_source_crit = [
'gmb'
]
local_listings_source_regex = "|".join(local_listings_source_crit)
partner_source_crit = [
'vegas community',
'new orleans community',
'dc community',
]
partner_source_regex = "|".join(partner_source_crit)
Функция:
def network_parse(df):
if isinstance(df['landing_page_url'], str):
if bool(re.search(fb_landing_page_regex,df['landing_page_url'].lower())) or bool(re.search(fb_source_regex,df['source_name'].lower())):
return 'Facebook'
if bool(re.search(google_landing_page_regex,df['landing_page_url'].lower())) or bool(re.search(google_source_regex,df['source_name'].lower())):
return 'Google'
if bool(re.search(local_listings_source_regex,df['source_name'].lower())):
return 'Local Listings'
if bool(re.search(partner_source_regex,df['source_name'].lower())):
return 'Partner - Community Partnership'
else:
return 'Other'
else:
return 'Other'
Вызов функции:
df['network'] = df.apply(network_parse, axis=1)
Ответ №2:
Прямо сейчас проблема заключается не any
в этом, а в x in df['source_name']
части (я взял source_name
, поскольку там проще объяснить). Вы проверяете, равна ли какая-либо строка фрейма данных (например) 'Google'
, а не содержит ли она слово. Для достижения последнего вы можете вложить for
операторы:
...
if any((x in y for y in df['landing_page_url']) for x in fb_landing_page_crit):
return 'Facebook'
Однако я почти уверен, что это не самый элегантный и эффективный способ, поскольку он многократно повторяет один и тот же столбец, но для небольших фреймов данных это может быть нормально. В противном случае это может помочь вам найти более эффективное решение.
Редактировать: чтобы исследовать вашу проблему, вы можете запустить следующие два фрагмента, где первый дает False
, а второй дает True
:
test = ['This', 'thought']
a = ['This is', 'a', 'longer Text than', 'I thought']
print(any(x in in a for x in test)) # This is principally what you coded
test2 = ['This', 'I thought']
print(any(x in a for x in test2)