python标准库之itertools

1. groupby

1.1 案例

先看一个例子

from itertools import groupby

str = '42m偏差'
ret = [''.join(list(g)) for k, g in groupby(str, key=lambda x: x.isdigit())]
print(ret)

# ['42', 'm偏差']

例子

str = '42m偏差'
for key, group in groupby(str):
    print(key, ' :',  list(group))
print('------------------------------------')

for key, group in groupby(str, key=lambda x: x.isdigit()):
    print(key, ' :', list(group))
print('------------------------------------')

for key, group in groupby(str, key=lambda x: x.isdigit()):
    print(key, ' :', ''.join(list(group)))

输出:

4  : ['4']
2  : ['2']
m  : ['m']: ['偏']: ['差']
------------------------------------
True  : ['4', '2']
False  : ['m', '偏', '差']
------------------------------------
True  : 42
False  : m偏差
[k for k, g in groupby('150m', lambda x: x.isdigit())]
Out[8]: [True, False]  # 按[True, False]是否为数字进行分组
[k for k, g in groupby('150m')]
Out[9]: ['1', '5', '0', 'm']
#  无法拆分字母和汉字,只能将数字提取出来
[list(g) for k, g in groupby('100m水平0风向10', key=lambda x: x.isdigit())]
Out[6]: [['1', '0', '0'], ['m', '水', '平'], ['0'], ['风', '向'], ['1', '0']]

[''.join(list(g)) for k, g in groupby('100m水平0风向10', key=lambda x: x.isdigit())]
Out[7]: ['100', 'm水平', '0', '风向', '10']

1.2 原理

groupby()的作用就是把可迭代对象中相邻的重复元素挑出来放一起,举个例子:

for key, group in groupby('AAABBBCCAAA'):
    print(key, list(group))

输出:

A ['A', 'A', 'A']
B ['B', 'B', 'B']
C ['C', 'C']
A ['A', 'A', 'A']

其中变量 key 表示的是重复元素,group 是一个itertools._grouper类型的变量,也是个迭代对象,list(group)表示的是将迭代对象转化为列表。

具体原理如下图所示:
在这里插入图片描述
实际上挑选规则是通过函数完成的,只要作用于函数的两个元素返回的值相等,这两个元素就被认为是在一组的,而函数返回值作为组的key。如果我们要忽略大小写分组,就可以让元素’A’和’a’都返回相同的key:

for key, group in groupby('AaaBBbcCAAa', lambda c: c.upper()):
     print(key, list(group))

A ['A', 'a', 'a']
B ['B', 'B', 'b']
C ['c', 'C']
A ['A', 'A', 'a']

具体原理如下图所示:
在这里插入图片描述

1.3 骚操作

有这么一个情形,要处理pandas.DataFrame表格数据,如下图所示,value 这一列有很多连续的空值,空值处理需求如下:

  • 连续空值行数超过10次的行全部按行删掉;
  • 连续空值行数小于等于10次的,则取上一个实数值和下一个实数值的均值来补全。

试问该怎么做?
在这里插入图片描述
答案:

NUM_NAN = 10
 
nan_r, _ = np.where(np.isnan(df))  # 找到所有NaN的值位置,nan_r表示行标,占位符_表示列标
 
# 统计哪一块数据应该删除
nan_list = []  # 只收集连续空值超过NUM_NAN个数的行索引
fun = lambda x: x[1] - x[0]
for k, g in groupby(enumerate(nan_r), fun):
    find_list = [j for i, j in g]  # 连续数字的列表
    if len(find_list) > NUM_NAN:  # 时间连续的点超过NUM_NAN个就删掉
        nan_list = nan_list + find_list
 
# 存较大片的缺省值,进行删除
if len(nan_list) != 0:
    df = df.reset_index()
    df = df.drop(nan_list)
    df = df.set_index(df['time'])
    df = df.drop(['time'], axis=1)
    
# 缺省值取前一行和后一行的均值
df = (df.fillna(method='backfill') + df.fillna(method='pad')) / 2
 
df.to_csv('test.csv')

2.使用itertools.product()

它提供了一种称为product的方法,该方法将所有元素配对。找到对后,我们可以过滤对。

#导入模块
import itertools

#初始化列表
list_1 = [1, 2, 3, 4, 5]
list_2 = [5, 8, 7, 1, 3, 6]

# 配对
pairs = itertools.product(list_1, list_2)
print(pairs)  

#过滤配对
result = [pair for pair in pairs if pair[0] != pair[1]]
print(result)

如果运行上面的代码,则将得到以下结果。
输出结果:

Out[0]: <itertools.product at 0x20a19b0b980>  # pairs
Out[1]:
[(1, 5), (1, 8), (1, 7), (1, 3), (1, 6), (2, 5), (2, 8), (2, 7), (2, 1),
(2, 3), (2, 6), (3, 5), (3, 8), (3, 7), (3, 1), (3, 6), (4, 5), (4, 8),
(4, 7), (4, 1), (4, 3), (4, 6), (5, 8), (5, 7), (5, 1), (5, 3), (5, 6)]

3.itertools.combinations()

ws_list
Out[1]: ['WS_150m_thies', 'WS_100m_thies', 'WS_30m_NRG']

ws_sum = list(itertools.combinations(ws_list, 2))
ws_sum
Out[2]: 
[('WS_150m_thies', 'WS_100m_thies'),
 ('WS_150m_thies', 'WS_30m_NRG'),
 ('WS_100m_thies', 'WS_30m_NRG')]
equal_ws = [57.5, 60, 80, 95, 110, 130, 150, 170, 190, 210, 222.5]
a = map(lambda x,y: (x,y), equal_ws[0:-1],equal_ws[1::]) 
list(a)
Out[30]: 
[(57.5, 60),
 (60, 80),
 (80, 95),
 (95, 110),
 (110, 130),
 (130, 150),
 (150, 170),
 (170, 190),
 (190, 210),
 (210, 222.5)]

4. itertools.chain

二维数组降维1维数组

import numpy as np
a = np.array([[1, 2], [3, 4], [9, 8]])

# 使用库函数
from itertools import chain
a_a = list(chain.from_iterable(a))
print(a_a)

输出结果为:[1, 2, 3, 4, 9, 8]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值