У меня есть один столбец, содержащий все данные, которые выглядят примерно так (значения, которые необходимо разделить, помечены как (c)):

UK (c)
London
Wales
Liverpool
US (c)
Chicago
New York
San Francisco
Seattle
Australia (c)
Sydney
Perth

И я хочу, чтобы он разделился на две колонки, выглядящие так:

London          UK
Wales           UK
Liverpool       UK
Chicago         US
New York        US
San Francisco   US
Seattle         US
Sydney          Australia
Perth           Australia

Вопрос 2: Что делать, если в странах не было такой картины, как (с)?

16
Tsatsa 27 Июн 2019 в 16:59

5 ответов

Лучший ответ

Шаг за шагом с endswith и ffill + str.strip

df['country']=df.loc[df.city.str.endswith('(c)'),'city']
df.country=df.country.ffill()
df=df[df.city.ne(df.country)]
df.country=df.country.str.strip('(c)')
10
YO and BEN_W 27 Июн 2019 в 14:16

Вы можете использовать np.where с < a href = "https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.str.contains.html" rel = "nofollow noreferrer"> str.contains слишком:

mask = df['places'].str.contains('(c)', regex = False)
df['country'] = np.where(mask, df['places'], np.nan)
df['country'] = df['country'].str.replace('\(c\)', '').ffill()
df = df[~mask]
df
            places     country
1          London         UK 
2           Wales         UK 
3       Liverpool         UK 
5         Chicago         US 
6        New York         US 
7   San Francisco         US 
8         Seattle         US 
10         Sydney  Australia 
11          Perth  Australia 

Str содержит ищет (c) и, если присутствует, вернет True для этого индекса. Если это условие истинно, значение страны будет добавлено в столбцы страны.

5
Mohit Motwani 27 Июн 2019 в 14:13

Вы можете сделать следующее:

data = ['UK (c)','London','Wales','Liverpool','US (c)','Chicago','New York','San Francisco','Seattle','Australia (c)','Sydney','Perth']
df = pd.DataFrame(data, columns = ['city'])
df['country'] = df.city.apply(lambda x : x.replace('(c)','') if '(c)' in x else None)
df.fillna(method='ffill', inplace=True)
df = df[df['city'].str.contains('\(c\)')==False]

< Сильный > Выход

+-----+----------------+-----------+
|     |     city       |  country  |
+-----+----------------+-----------+
|  1  | London         | UK        |
|  2  | Wales          | UK        |
|  3  | Liverpool      | UK        |
|  5  | Chicago        | US        |
|  6  | New York       | US        |
|  7  | San Francisco  | US        |
|  8  | Seattle        | US        |
| 10  | Sydney         | Australia |
| 11  | Perth          | Australia |
+-----+----------------+-----------+
3
Sebastien D 27 Июн 2019 в 14:23

Сначала вы можете использовать {{X0} } чтобы найти города, оканчивающиеся на (c), и извлечь название страны и ffill для заполнения нового country столбца.

Те же извлеченные совпадения можно использовать для определения местоположения удаляемых строк, то есть строк, которые являются notna:

m = df.city.str.extract('^(.*?)(?=\(c\)$)')
ix = m[m.squeeze().notna()].index
df['country'] = m.ffill()
df.drop(ix)

            city     country
1          London         UK 
2           Wales         UK 
3       Liverpool         UK 
5         Chicago         US 
6        New York         US 
7   San Francisco         US 
8         Seattle         US 
10         Sydney  Australia 
11          Perth  Australia 
6
yatu 27 Июн 2019 в 14:17

extract и ffill

Начните с extract и ffill, затем удалите лишние строки.

df['country'] = (
    df['data'].str.extract(r'(.*)\s+\(c\)', expand=False).ffill())
df[~df['data'].str.contains('(c)', regex=False)].reset_index(drop=True)

            data    country
0         London         UK
1          Wales         UK
2      Liverpool         UK
3        Chicago         US
4       New York         US
5  San Francisco         US
6        Seattle         US
7         Sydney  Australia
8          Perth  Australia

Где,

df['data'].str.extract(r'(.*)\s+\(c\)', expand=False).ffill()

0            UK
1            UK
2            UK
3            UK
4            US
5            US
6            US
7            US
8            US
9     Australia
10    Australia
11    Australia
Name: country, dtype: object

Шаблон '(.*)\s+\(c\)' соответствует строкам формы «страна (с)» и извлекает название страны. Все, что не соответствует этому шаблону, заменяется на NaN, поэтому вы можете удобно заполнять строки вперед.


split с np.where и ffill

Это распадается на "(с)".

u = df['data'].str.split(r'\s+\(c\)')
df['country'] = pd.Series(np.where(u.str.len() == 2, u.str[0], np.nan)).ffill()

df[~df['data'].str.contains('(c)', regex=False)].reset_index(drop=True)

            data    country
0         London         UK
1          Wales         UK
2      Liverpool         UK
3        Chicago         US
4       New York         US
5  San Francisco         US
6        Seattle         US
7         Sydney  Australia
8          Perth  Australia
7
cs95 27 Июн 2019 в 14:16