看过来
《pandas 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gairuo123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
本需求利用映射思维,我们解决一个计算元素出现最早的行数的问题。在解决问题过程中,我们需要与一个映射表,供我们与源数据操作,来获得最终的结果。这种思维的解题步聚一般是构造映射表,再利用映射表进行操作得到结果。
我们构造数据如下:
import pandas as pd
import io
data = (['a', 's'],
['b'],
['c','b', 's'],
['c', 'c', 't'],
['t']
)
df = pd.DataFrame({'data': data})
df
'''
data
0 [a, s]
1 [b]
2 [c, b, s]
3 [c, c, t]
4 [t]
'''
这个数据只要 data 一列,每个值是一个列表,我们要增加一列,对应值为 data 中所有元素第一次出现在表中最早的行数,结果即:
'''
data foo
0 [a, s] 1
1 [b] 2
2 [c, b, s] 1
3 [c, c, t] 3
4 [t] 4
'''
比如,索引 2 的列表中 3 个元素,s 出现在第一行,为最小的行数,所以值为 1。
先对 data 列进行爆炸,这样所展开了所有的元素,注意,索引是此元素所在的行索引。再删除掉重复的元素,就只剩下所有的不重复的值,索引加 1 就是我们说的元素首次出现的序号。
再构造映射表(字典),键为元素,值为首次出现的行序号。
再用map()
迭代原始 df 的 data 列,用推导式逐个利用映射表计算首次出现的行号,再取最小值,这样就得到想要的数据。
爆炸 data 列,再删除重复值:
df.data.explode()
'''
0 a
0 s
1 b
2 c
2 b
2 s
3 c
3 c
3 t
4 t
Name: data, dtype: object
'''
df.data.explode().drop_duplicates()
'''
0 a
0 s
1 b
2 c
3 t
Name: data, dtype: object
'''
对索引标签值加 1:
ser = df.data.explode().drop_duplicates().rename(lambda x: x+1)
ser
'''
1 a
1 s
2 b
3 c
4 t
Name: data, dtype: object
'''
构造映射表(字典),键为元素,值为首次出现的行序号:
_map = {v:i for i, v in ser.items()}
_map
# {'a': 1, 's': 1, 'b': 2, 'c': 3, 't': 4}
迭代计算每个列表中,每个元素首次出现的行号,再取最小行号。
no = df.data.map(lambda x: min(_map.get(i) for i in x))
no
'''
0 1
1 2
2 1
3 3
4 4
Name: data, dtype: int64
'''
将计算结果增加到原数据中,成为一列:
df.assign(foo=no)
'''
data foo
0 [a, s] 1
1 [b] 2
2 [c, b, s] 1
3 [c, c, t] 3
4 [t] 4
'''
到此,我们完成了这个需求。
(完)
更新时间:2024-08-18 16:22:25 标签:pandas python 行数