将列重塑为多列

2024-06-28 19:56:02 发布

您现在位置:Python中文网/ 问答频道 /正文

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

我找到了一种使用字典的方法,但是由于我想保持顺序,所以我正在寻找一种使用列表的方法。你知道吗

我尝试了基于索引和价值本身(特别是[国家]和[城市])的方法,但都失败了。非常感谢您的帮助!你知道吗


Tags: 方法citydatacountrypdv1parisfrance
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)

这将起作用:

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列中的值。你知道吗

相关问题 更多 >