需求:
将 c1 按逗号拆分,爆炸为一行一行数据,然后将 c1 后边的有逗号的扩展成行,没逗号的只写在第一行。
思路:
- 先将 DataFrame 中有逗号的值分拆转为列表,接下来我们对 c1
进行爆炸,就得到了整个数据的基本框架,在这个框架上我们修改调整数据。 - 将 a、b 两列设置为索引,这样我们就只处需要处理的逻辑(当然 c1
也不需要再处理了,也可以设置为索引),在最后需要处理完成了再重置回来。 - 写一个数据处理函数,用索引分组后的 transform() 来应用,因为 transform()
返回的是对每个列的处理,返回的相同形状的数据。 - 关键是这个函数的逻辑:
- 对 c1 不处理,直接返回
- 如果这个无 Series 的第一个值是列表,我们就要修改数据,按以下几步: 计算我们要多少个空格
- 将第一个值(列表),与计算后的空格拼接形成一个与原列相同长度的列表
- 将这个列表返回,这样会覆盖到原列数据
- 如果不是列表,只将第一个值与其他空格组成列表返回,逻辑和上述过程一样
二、使用步骤
1.引入库
代码如下(示例):
import pandas as pd
import io
2.读入数据
代码如下(示例):
data ='''
a b c1 c2 c3 c4
A W 1,2,3 1,2 1,3,3 g
B X 1,2,3,4,5 k 1,4,7 h
'''
df = pd.read_csv(io.StringIO(data),sep='\s+')
df
# 先将有逗号的值拆分成列表:
df.map(lambda x: x.split(',') if ',' in x else x)
# 爆炸 c1 列,设置索引:
(
df.map(lambda x: x.split(',') if ',' in x else x)
.explode('c1')
.set_index(['a', 'b'])
)
# 分组,按思路逻辑编写处理函数:
def func(s: pd.Series):
first = s.iloc[0]
if s.name == 'c1':
return s
elif isinstance(first, list):
space_len = len(s) - len(first)
values = first + ['']*space_len
return values
else:
values = [first] + ['']*(len(s)-1)
return values
(
df.map(lambda x: x.split(',') if ',' in x else x)
.explode('c1')
.set_index(['a', 'b'])
.groupby(level=[0, 1])
.transform(func)
.reset_index()
)
总结
以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。