2016-12-20 3 views
4

Я довольно новичок в Python, и у меня проблемы. У меня есть следующий dataframe:Переставить столбец в несколько столбцов

import pandas as pd 
data = {'v1':('Belgium[country]', 'Antwerp[city]', 'Gent[city]', 'France[country]', 'Paris[city]', 'Marseille[city]', 'Toulouse[city]', 'Spain[country]', 'Madrid[city]')} 
df = pd.DataFrame(data) 
df 

    v1 
0 Belgium[country] 
1 Antwerp[city] 
2 Gent[city] 
3 France[country] 
4 Paris[city] 
5 Marseille[city] 
6 Toulouse[city] 
7 Spain[country] 
8 Madrid[city] 

Что я хочу отобразить в следующем формате:

v1    v2 
0 Belgium[country] Antwerp[city] 
1 Belgium[country] Gent[city] 
2 France[country] Paris[city] 
3 France[country] Marseille[city] 
4 France[country] Toulouse[city] 
5 Spain[country] Madrid[city] 

Я нашел способ сделать это с помощью словаря, но так как я хочу, чтобы поддерживать порядок I Я ищу способ сделать это, используя список или около того.

Я пробовал его как на основе индексов, так и на самих значениях (в частности [страна] и [город]), но я не смог с ними справиться. Любая помощь высоко ценится!

+0

В вашем примере определения все страны отмечены как города. – IanS

+0

Вы правы, я исправил его – LRA

ответ

2

Это будет работать:

counter = df['v1'].str.contains('country').cumsum() 
result = df.groupby(counter).apply(lambda g: g[1:]).reset_index(level=1, drop=True) 
result = result.rename(columns={'v1': 'v2'}).reset_index(drop=False) 
result['v1'] = result['v1'].replace(df.groupby(counter).first().squeeze()) 

Идея заключается в том, чтобы добавить счетчик, который увеличивается для каждой новой страны. Затем вы можете группировать этот счетчик для доступа к необходимой вам информации.

В частности, первым шагом является сохранение только городов (g[1:] для каждой группы g). Затем выполните переименование и переиндексацию. Наконец, используйте результат из другой группы (дающей стране), чтобы заменить значения в столбце v1.

+0

Это работает отлично, спасибо! – LRA

2

Решение без groupby:

#rename columns 
df = df.rename(columns={'v1':'v2'}) 
#get counter 
counter= df.v2.str.contains('country').cumsum() 
#get mask where are changed country to city 
df.insert(0, 'v1', df.loc[counter.ne(counter.shift()), 'v2']) 
#forward filling NaN 
df.v1 = df.v1.ffill() 
#remove rows where v1 == v2 
df = df[df.v1.ne(df.v2)].reset_index(drop=True) 

print (df) 
       v1    v2 
0 Belgium[country] Antwerp[city] 
1 Belgium[country]  Gent[city] 
2 France[country]  Paris[city] 
3 France[country] Marseille[city] 
4 France[country] Toulouse[city] 
5 Spain[country]  Madrid[city] 

Timings:

In [189]: %timeit (jez(df)) 
100 loops, best of 3: 2.47 ms per loop 

In [191]: %timeit (IanS(df1)) 
100 loops, best of 3: 5.06 ms per loop 

Код для таймингов:

def jez(df): 
    df = df.rename(columns={'v1':'v2'}) 
    counter= df.v2.str.contains('country').cumsum() 
    df.insert(0, 'v1', df.loc[counter.ne(counter.shift()), 'v2']) 
    df.v1 = df.v1.ffill() 
    df = df[df.v1.ne(df.v2)].reset_index(drop=True) 

    return (df) 

def IanS(df): 
    counter = df['v1'].str.contains('country').cumsum() 
    result = df.groupby(counter).apply(lambda g: g[1:]).reset_index(level=1, drop=True) 
    result = result.rename(columns={'v1': 'v2'}).reset_index(drop=False) 
    result['v1'] = result['v1'].replace(df.groupby(counter).first().squeeze()) 
    return (result) 
+0

Также работает, спасибо! – LRA

Смежные вопросы