Reinaldo Chaves
Reinaldo Chaves

Reputation: 995

Split a column in pandas twice to multiple columns

I have a column "Nome_propriedade" with complete addresses, such as establishment name, streets, neighborhood, city and state

It always ends with the name of the city and state. With this pattern:

Nome_propriedade
"Rod. BR 386, bairro Olarias/Conventos, Lajeado/RS"
"Fazenda da Várzea - zona rural, Serro/MG"
"Cidade do Rock - Jacarepaguá, Rio de Janeiro/RJ"
"Área de extração de carnaúba - Povoado Areal, zona rural, Santa Cruz do Piauí/PI"
"Pastelaria - Av. Vicente de Carvalho, 995, Loja Q, Vila da Penha, Rio de Janeiro/RJ"

I want to create two new columns, "city" and "state", and fill them with the last values found in column "Nome_propriedade". I also want to stip those away from Nome_propiedade.

                           Nome_propriedade                 City State
      Rod. BR 386, bairro Olarias/Conventos              Lajeado    RS
             Fazenda da Várzea - zona rural                Serro    MG
            Cidade do Rock - Jacarepaguá...       Rio de Janeiro    RJ
Área de extração de carnaúba - Povoado A...  Santa Cruz do Piauí    PI
Pastelaria - Av. Vicente de Carvalho, 99...       Rio de Janeiro    RJ

Please anyone know how I can create these two columns?

I can not do a general split because I just want to separate the city and state information. Other information may remain unchanged.

Upvotes: 3

Views: 2100

Answers (4)

Anton vBR
Anton vBR

Reputation: 18906

Here is an effective solution avoiding the tedious apply and simply sticking with str-operations.

df["Nome_propriedade"], x = df["Nome_propriedade"].str.rsplit(', ', 1).str
df["City"], df['State'] = x.str.split('/').str

Full example:

import pandas as pd

propiedades = [
    "Rod. BR 386, bairro Olarias/Conventos, Lajeado/RS",
    "Fazenda da Várzea - zona rural, Serro/MG",
    "Cidade do Rock - Jacarepaguá, Rio de Janeiro/RJ",
    "Área de extração de carnaúba - Povoado Areal, zona rural, Santa Cruz do Piauí/PI",
    "Pastelaria - Av. Vicente de Carvalho, 995, Loja Q, Vila da Penha, Rio de Janeiro/RJ"
]

df = pd.DataFrame({
    "Nome_propriedade":propiedades
})

df["Nome_propriedade"], x = df["Nome_propriedade"].str.rsplit(', ', 1).str
df["City"], df['State'] = x.str.split('/').str

# Stripping Nome_propriedade to len 40 to fit screen
print(df.assign(Nome_propriedade=df['Nome_propriedade'].str[:40]))

Returns:

                           Nome_propriedade                 City State
0     Rod. BR 386, bairro Olarias/Conventos              Lajeado    RS
1            Fazenda da Várzea - zona rural                Serro    MG
2              Cidade do Rock - Jacarepaguá       Rio de Janeiro    RJ
3  Área de extração de carnaúba - Povoado A  Santa Cruz do Piauí    PI
4  Pastelaria - Av. Vicente de Carvalho, 99       Rio de Janeiro    RJ

If you'd like to keep the items:

df["City"], df['State'] = df["Nome_propriedade"]\
                            .str.rsplit(', ', 1).str[-1]\ 
                            .str.split('/').str

Upvotes: 2

rpanai
rpanai

Reputation: 13437

What do you think about:

import pandas as pd
propiedades = ["Rod. BR 386, bairro Olarias/Conventos, Lajeado/RS",
               "Fazenda da Várzea - zona rural, Serro/MG",
               "Cidade do Rock - Jacarepaguá, Rio de Janeiro/RJ",
               "Área de extração de carnaúba - Povoado Areal, zona rural, Santa Cruz do Piauí/PI",
               "Pastelaria - Av. Vicente de Carvalho, 995, Loja Q, Vila da Penha, Rio de Janeiro/RJ"]
df = pd.DataFrame({"Nome_propriedade":propiedades})

df[["City", "State"]] = df["Nome_propriedade"].apply(lambda x :x.split(",")[-1]).str.split("/",
                                                                                           expand=True)

UPDATE If you then want to delete these infos from Nome_propriedade you can add this line

df["Nome_propriedade"] = df["Nome_propriedade"].apply(lambda x :",".join(x.split(",")[:-1]))

Upvotes: 3

Engineero
Engineero

Reputation: 12908

The easiest approach I can see is, for a single example:

example = 'some, stuff, here, city/state'
elements = example.split(',')
city, state = elements[-1].split('/')

To apply this to the column in your dataframe:

df['city_state'] = df.Nome_propriedade.apply(lambda r: r.split(',')[-1].split('/'))
df['city'] = [cs[0] for cs in df['city_state']]
df['state'] = [cs[1] for cs in df['city_state']]

For example:

example2 = 'another, thing here city2/state2'
df = pd.DataFrame({'address': [example, example2],
                   'other': [1, 2]})
df['city_state'] = df.address.apply(lambda r: r.split()[-1].split('/'))
df['city'] = [cs[0] for cs in df['city_state']]
df['state'] = [cs[1] for cs in df['city_state']]
df.drop(columns=['city_state'], inplace=True)
print(df)
#                             address  other   city   state
# 0     some, stuff, here, city/state      1   city   state
# 1  another, thing here city2/state2      2  city2  state2

Note: some of the other answers provide a more efficient way to unpack the result into your dataframe. I'll leave this here because I think breaking it out into steps is illustrative, but for efficiency sake, I'd go with one of the others.

Upvotes: 1

harpan
harpan

Reputation: 8631

You need to split the string in the column by ,, takw the last element in the list and split it by /. That list is your two columns.

pd.DataFrame(list(df['Nome_propriedade'].str.split(',').apply(lambda x: x[-1]).str.split('/')), columns=['city', 'state'])

Output:

                   city    state
0               Lajeado    RS
1                 Serro    MG
2        Rio de Janeiro    RJ
3   Santa Cruz do Piauí    PI
4        Rio de Janeiro    RJ

Upvotes: 3

Related Questions