#python #pandas #list #dataframe #list-comprehension
#python #pandas #Список #Фрейм данных #понимание списка
Вопрос:
Я пытаюсь создать новый столбец, содержащий названия городов. У меня также есть список, содержащий необходимые названия городов, и файлы CSV, в которых названия городов указаны под разными именами столбцов.
Что я пытаюсь сделать, так это проверить, существуют ли названия городов в списке в определенном диапазоне столбцов CSV-файлов, и заполнить это конкретное название города в новом столбце City.
Мой код:
import pandas as pd
import numpy as np
City_Name_List = ['Amsterdam', 'Antwerp', 'Brussels', 'Ghent', 'Asheville', 'Austin', 'Boston', 'Broward County',
'Cambridge', 'Chicago', 'Clark County Nv', 'Columbus', 'Denver', 'Hawaii', 'Jersey City', 'Los Angeles',
'Nashville', 'New Orleans', 'New York City', 'Oakland', 'Pacific Grove', 'Portland', 'Rhode Island', 'Salem Or', 'San Diego']
data = {'host_identity_verified':['t','t','t','t','t','t','t','t','t','t'],
'neighbourhood':['Amsterdam, North Holland, Netherlands', 'Amsterdam, North Holland, Netherlands', 'NaN',
'Amsterdam, North Holland, Netherlands', 'Amsterdam, North Holland, Netherlands',
'Amsterdam, North Holland, Netherlands', 'Amsterdam, North Holland, Netherlands', 'NaN',
'Amsterdam, North Holland, Netherlands', 'Amsterdam, North Holland, Netherlands'],
'neighbourhood_cleansed':['Oostelijk Havengebied - Indische Buurt', 'Centrum-Oost', 'Centrum-West', 'Centrum-West', 'Centrum-West',
'Oostelijk Havengebied - Indische Buurt', 'Centrum-Oost', 'Centrum-West', 'Centrum-West', 'Centrum-West'],
'neighbourhood_group_cleansed': ['NaN','NaN','NaN','NaN','NaN','NaN','NaN','NaN','NaN','NaN'],
'latitude':[ 52.36575, 52.36509, 52.37297, 52.38761, 52.36719, 52.36575, 52.36509, 52.37297, 52.38761, 52.36719]}
df = pd.DataFrame(data)
df['City'] = [x for x in City_Name_List if x in df.loc[:,'host_identity_verified':'latitude'].values][0]
Когда я запускаю код, я получаю это сообщение:
Traceback (most recent call last):
File "C:/Users/YAZAN/PycharmProjects/Yazan_Work/try.py", line 63, in <module>
df['City'] = [x for x in City_Name_List if x in df.loc[:,'host_identity_verified':'latitude'].values][0]
IndexError: list index out of range
Это связано с тем, что за городом Амстердам в данных следуют другие слова.
Я хочу, чтобы мой вывод был следующим:
0 Amsterdam
1 Amsterdam
2 Amsterdam
3 Amsterdam
4 Amsterdam
5 Amsterdam
6 Amsterdam
7 Amsterdam
8 Amsterdam
9 Amsterdam
Name: City, dtype: object
Я неустанно пытался решить эту проблему. Я пытался использовать endswith
, startswith
, регулярное выражение, но безрезультатно. Возможно, я неправильно использую оба метода. Я надеюсь, что кто-нибудь сможет мне помочь.
Ответ №1:
Базовое решение с использованием Pandas.DataFrame.Apply
df['City'] = df.apply(
lambda row: [x if x in row.loc['neighbourhood'] for x in City_Name_List][0],
axis=1
)
После выполнения вышеизложенного df['city']
будет содержать город (определяемый его включением в City_Name_List
), если он найден в 'neighbourhood'
столбце каждой строки.
Модифицированное решение
Вы могли бы немного более четко указать, что City
я должен заполнять первую подстроку, присутствующую перед первым вхождением ,
в 'neighbourhood'
поле каждой строки. Это может быть хорошей идеей, если 'neighbourhood'
столбец надежно однороден по структуре, поскольку это может помочь предотвратить любое нежелательное поведение, возникающее из городов с одинаковыми именами, городов, которые являются подстроками других городов в City_Name_List
etc.
df['City'] = df.apply(
lambda row: [x if x in row.loc['neighbourhood'].split(',')[0] for x in City_Name_List][0],
axis=1
)
Примечание: Приведенные выше решения являются просто примерами того, как вы можете решить возникающие у вас проблемы. Они не учитывают правильную обработку исключений, крайних случаев и т. Д. Как всегда, вы должны позаботиться о том, чтобы учесть такие соображения в своем коде.
Комментарии:
1. Спасибо за ваш ответ. При применении вашего кода я также получил NaN в новом столбце. Но я изменил np.nan на x, и он заполнил его желаемым названием города. Очень признателен. Один маленький вопрос, не все мои файлы данных имеют название города в столбце с именем neighborhood Я знаю, что название города расположено между столбцами host_identity_verified и latitude . Как я могу изменить код, чтобы зафиксировать это?
Ответ №2:
df['City'] = df['neighbourhood'].apply(lambda x: [i for i in x.split(',') if i in City_Name_List])
df['City'] = df['City'].apply(lambda x: "" if len(x) == 0 else x[0])
Комментарии:
1. Apply работает медленнее, чем векторизованные
Series.str
методы в pandas2. Пожалуйста, отправьте векторизированный ответ 🙂
3. Спасибо за ваш ответ. Я частично получил то, что хотел, но когда в исходном столбце есть значения NaN, строка в новом столбце оказывается пустой. Еще одна вещь, поскольку я работаю с более чем 2000 CSV-файлами, и не во всех из них есть столбец с именем neighborhood, но я знаю, что название города расположено между столбцами host_identity_verified и latitude, возможно ли сохранить df.loc[:,’host_identity_verified’:’широта’] в коде?
4.
df['neighbourhood'].str.split(',')[0]
в ответе @LiamFiddler приведен пример векторизованного метода str в pandas, который вы, вероятно, уже знаете. Он удаляет по крайней мере одно понимание apply или list. У меня такое чувство, что его вариант использования сложнее, чем можно легко ответить.5. У меня был неуместный индексатор, который заставлял его вести себя неправильно, но общее решение работает.
Ответ №3:
Проблема в том, что когда вы говорите x in df.loc[]
, что проверяете не то, есть ли название города в каждой конкретной строке, а то, есть ли название города во всей серии, чего нет. Что вам нужно, это что-то вроде этого:
df['city'] = [x if x in City_Name_list else '' for x[0] in df['neighbourhood'].str.split(',')]
Это разделит каждую строку в df[‘neighborhood’] вдоль запятых и вернет первое значение, затем проверьте, есть ли это значение в вашем списке названий городов, и если да, то поместите его в серию ‘city’.
Комментарии:
1. Я получаю эту ошибку при запуске кода: «Длина значений» Ошибка значения: длина значений (1) не соответствует длине индекса (10)
2. О, я прошу прощения, я не видел всех данных и понимаю, что есть значения NaN. В этом понимании списка должно быть предложение else.
3. Это привело бы к отсутствию значения для city для каждого значения в dataframe, поэтому разница в длине вызывает проблему. Я обновил свой ответ.
4. Прошу прощения, но код все равно не работал. Я очень благодарен за то, что вы нашли время для проверки моего вопроса. Очень признателен.
5. Я понял, что у меня неуместный индексатор. [0] должен идти после x, а не метод .str.split() . Вызов [0] для этого метода возвращает только первую строку в фрейме данных. Ответ был исправлен, но рад видеть, что вы нашли решение, которое работает.