我对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])尝试了它,但是我都失败了。非常感谢任何帮助!
答案 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)