首页 > 解决方案 > Pandas - 将数据从单行分成多行

问题描述

我有一个数据框,其中包含以下格式的一些客户详细信息(有时不止一个城市映射到特定的 cust_id):

cust_id, cust_location
1001, id:ref_101
      desc: Chicago, Illinois
      type: city

      id:ref_102
      desc: NewYork, NewYork
      type: city

      id:ref_103
      desc: Saint Joseph, MO
      type: city
1002, id:ref_106
      desc: Chillicothe, MO
      type: city

      id:ref_107
      desc: NewYork, NewYork
      type: city

我试图打破这一点,以便得到以下结构:

cust_id,cust_location
1001, Chicago, Illinois
1001, NewYork, NewYork
1001, Saint Joseph, MO
1002, Chillicothe, MO
1002, NewYork, NewYork

如果特定的 cust_id 有多个条目,则它由空行分隔,如示例数据中所示。我使用的是 pandas 0.23 版本,所以我无法使用 0.25 及更高版本中提供的爆炸选项

标签: pandas

解决方案


解决方案取决于实际数据 - 这里有 2 列 - 首先是cust_id用空格填充(或 NaN 也可以工作),其次是另一个数据由以下内容分割:

print (df)
   cust_id            cust_location
0     1001               id:ref_101
1           desc: Chicago, Illinois
2                        type: city
3                                  
4                        id:ref_102
5            desc: NewYork, NewYork
6                        type: city
7                                  
8                        id:ref_103
9            desc: Saint Joseph, MO
10                       type: city
11    1002               id:ref_106
12            desc: Chillicothe, MO
13                       type: city
14                                 
15                       id:ref_107
16           desc: NewYork, NewYork
17                       type: city

使用Series.wherewith Series.str.containsnumber 替换缺失值和前向填充值 by ffill,然后使用Series.str.split第二列和最后一个过滤器 by boolean indexingDataFrame.pop用于避免在下一步中删除:

df['cust_id'] = df['cust_id'].where(df['cust_id'].astype(str).str.contains('\d+')).ffill()
df[['a','cust_location']] = df['cust_location'].str.split(': ', expand=True)
print (df)
   cust_id      cust_location           a
0     1001               None  id:ref_101
1     1001  Chicago, Illinois        desc
2     1001               city        type
3     1001               None            
4     1001               None  id:ref_102
5     1001   NewYork, NewYork        desc
6     1001               city        type
7     1001               None            
8     1001               None  id:ref_103
9     1001   Saint Joseph, MO        desc
10    1001               city        type
11    1002               None  id:ref_106
12    1002    Chillicothe, MO        desc
13    1002               city        type
14    1002               None            
15    1002               None  id:ref_107
16    1002   NewYork, NewYork        desc
17    1002               city        type

df = df[df.pop('a').str.contains('desc')]
print (df)
   cust_id      cust_location
1     1001  Chicago, Illinois
5     1001   NewYork, NewYork
9     1001   Saint Joseph, MO
12    1002    Chillicothe, MO
16    1002   NewYork, NewYork

推荐阅读