将列重塑为多列

时间:2016-12-20 10:36:37

标签: python pandas indexing

我对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]

我找到了一种使用字典来实现此目的的方法,但由于我想保持顺序,我正在寻找一种方法来使用列表左右。

我根据索引和值本身(特别是[country]和[city])尝试了它,但是我都失败了。非常感谢任何帮助!

2 个答案:

答案 0 :(得分: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)。然后进行一些重命名和重建索引。最后,使用另一个groupby(给国家/地区)的结果替换v1列中的值。

答案 1 :(得分: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)