2016-12-20 27 views
4

我對Python很陌生,而且遇到了一些麻煩。我有以下數據框:將列重整爲多列

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] 

我找到了一種方法來做到這一點使用一本詞典,但因爲我要維護秩序我我正在尋找一種方式來使用列表左右來做到這一點。

我嘗試了基於索引和值本身(特別是[國家]和[城市]),但我都失敗了。任何幫助深表感謝!

+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)。然後做一些重命名和reindexing。最後,使用另一個groupby(給國家)的結果替換第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] 

時序

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