python - ¿Cómo creo una nueva columna en un marco de datos a partir de una columna existente usando condiciones?
pandas dataframe (5)
Tengo una columna que contiene todos los datos que se parecen a esto (los valores que deben separarse tienen una marca como (c)):
UK (c)
London
Wales
Liverpool
US (c)
Chicago
New York
San Francisco
Seattle
Australia (c)
Sydney
Perth
Y quiero que se divida en dos columnas con este aspecto:
London UK
Wales UK
Liverpool UK
Chicago US
New York US
San Francisco US
Seattle US
Sydney Australia
Perth Australia
Pregunta 2: ¿Qué pasaría si los países no tuvieran un patrón como (c)?
extract
y
ffill
Comience con
extract
y
ffill
, luego elimine las filas redundantes.
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
Dónde,
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
El patrón
''(.*)/s+/(c/)''
coincide con cadenas de la forma "country (c)" y extrae el nombre del país.
Cualquier cosa que no coincida con este patrón se reemplaza con NaN, por lo que puede reenviar el relleno en las filas.
split
con
np.where
y
ffill
Esto se divide en "(c)".
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
Paso a paso con
endswith
y
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)'')
Podrías hacer lo siguiente:
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]
Salida
+-----+----------------+-----------+
| | 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 |
+-----+----------------+-----------+
Primero puede usar
str.extract
para ubicar las ciudades que terminan en
(c)
y extraer el nombre del país, y
ffill
para completar una nueva columna de
country
.
Las mismas coincidencias extraídas se pueden usar para ubicar las filas que se deben eliminar, es decir, las filas que no son:
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
Puedes usar
np.where
con
str.contains
también:
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
La cadena contiene busca
(c)
y si está presente devolverá True para ese índice.
Cuando esta condición sea Verdadera, el valor del país se agregará a las columnas del país