Python- 分区判断的写法及其5种优化方法

问题

有存在随机的10000个数据,请用Python将判断每个数在哪个区间,并输出,区间分为,小于0,0到50,50到100,100 到1000,1000以上。

import pandas as pd

# 创建一个示例dataframe
data = {'values': [随机数据]} # 这里用一个列表来表示10000个随机数
df = pd.DataFrame(data)

# 定义每个区间的边界值
boundaries = [-1, 0, 50, 100, 1000, 10000]

# 初始化一个空列表,用于存储每个数所在的区间
intervals = []

# 遍历dataframe的每一行
for i, row in df.iterrows():
    value = row['values']
    # 遍历每个区间的边界值
    for j, bound in enumerate(boundaries):
        # 如果数小于或等于边界值,则判断为该区间
        if value <= bound:
            intervals.append(f"小于{bound}")
            break
    else:
        # 如果数不在前五个区间,则判断为1000以上
        intervals.append("1000以上")

# 输出结果
for i, interval in enumerate(intervals):
    print(f"数字{df['values'][i]}位于区间:{interval}")

详解

  • iterrows() 的用法:
    iterrows是pandas中的一个函数,用于在DataFrame中进行遍历,逐行返回一个元组index和Series。(需要注意的是,每个元组包含该行的索引和行数据。而行数据是Series类型。)

    import pandas as pd
    
    data = {'Column 1': [1, 2, 3, 4], 'Column 2': ['A', 'B', 'C', 'D'], 'Column 3': [10, 20, 30, 40]}
    df = pd.DataFrame(data)
    
    for index, row in df.iterrows():
        print(f"Index: {index}, Row data: {row}")
    
    

    输出结果:

    Index: 0, Row data: Column 1    1
    Column 2    A
    Column 3    10
    Name: 0, dtype: object
    Index: 1, Row data: Column 1    2
    Column 2    B
    Column 3    20
    Name: 1, dtype: object
    Index: 2, Row data: Column 1    3
    Column 2    C
    Column 3    30
    Name: 2, dtype: object
    Index: 3, Row data: Column 1    4
    Column 2    D
    Column 3    40
    Name: 3, dtype: object
    
  • enumerate() 的用法:

    enumerate是Python内置函数,可以用于在遍历一个可迭代的对象时,同时返回一个计数和相应的值。
    在处理DataFrame中的行时,可以使用enumerate函数获取每个行的序号并进行相应的处理。

    import pandas as pd
    df = pd.DataFrame({'ID': [1, 2, 3],
                      'Name': ['Tom', 'Jerry', 'Mike'],
                       'Age': [20, 22, 18]})
    # 使用`enumerate`遍历DataFrame数据,并输出每行数据的序号和'Name'列数据:
    for i, data in enumerate(df['Name']):
        print(i, data)
    

    输出结果:

    0 Tom
    1 Jerry
    2 Mike
    

    需要注意的是,enumerate返回的是一个元组(index, value),其中index就是每一行对应的序号,value是该行的数据。同时,我们也可以在for循环里面使用enumerate函数遍历DataFrame数据的行,使用iterrows不一样的是,for循环在每次迭代时不会创建一个Series类型的对象。

5种优化方法

和使用iterrows一样,使用enumerate遍历单个行仍然是一种非常慢的方法,因此,我们还是应该尽可能使用pandas内置的矢量化的操作,而不是循环行遍历DataFrame来优化DataFrame操作。
注意
cut函数无法直接处理开放区间的上界,可以用 float('inf')np.inf来表示正无穷大。且cut的bins长度必须大于labels 的长度。
法1
pd.cut()

import numpy as np
import pandas as pd#创建10000个随机数字
arr = np.random.rand(10000) * 3000

#创建区间范围
bins = [-np.inf, 0, 50, 100, 1000, np.inf]

#给区间加上标签
labels = ['<0', '0-50', '50-100', '100-1000', '>1000']

#将数字分组
result =pd.cut(arr, bins, labels = labels)

#统计每个区间内的数字数量
count = pd.value_counts(result)

#输出结果
print(count)

在使用pd.cut()函数时,它会返回一个用于后续分类数据统计的Categorical类型,该类型支持一些常见的操作。其中,pd.cut()函数的第一个参数是指定需要转化为分类变量的变量,第二个参数则是指定用于分的数值区间,第三个参数是区间对应的名称数组。

法2
np.digitize()函数将数字分组到不同的区间

import numpy as np
import pandas as pd
#创建10000个随机数字
arr = np.random.rand(10000) * 3000
#创建区间范围
bins = [-np.inf, 0, 50, 100, 1000, np.inf]
#给区间加上标签
labels = ['<0', '0-50', '50-100', '100-1000', '>1000']
#将数字分组并标记标签
result = labels[np.digitize(arr, bins)]
#统计每个区间内的数字数量
count = pd.value_counts(result)
#输出结果
print(count)

这个例子和使用pd.cut()函数类似。区别在于np.digitize()函数可以将数据组分成指定的分组,并返回一个表示分组索引的数组,然后使用索引数组标记出每个数所在的区间并返回所在的标签列表。
需要注意的是,在使用np.digitize()函数时,如果存在较小的值或较大的值,需要在去向数组bins的值中添加无穷的边界值(-np.Infnp.Inf)。同时,应该掌握不同函数之间的比较,选择最合适自己的方式。

法3

np.where()函数:

import numpy as np
import pandas as pd

# 创建10000个随机数字
arr = np.random.rand(10000) * 3000
# 定义区间边界值
bins = [0, 50, 100, 1000, np.inf]
# 给区间添加标签
labels = ['0-50', '50-100', '100-1000', '>1000']
# 利用np.where()函数实现分组
result = np.where(arr <= 0, '<0', pd.cut(arr, bins, labels=labels))
# 统计每个区间内的数字数量

count = pd.value_counts(result)
# 输出结果
print(count)

这个示例使用了np.where()函数根据条件筛选出每个数字属于的数据区间,并返回对应的标签。如果数字小于等于0,则返回’<0’,否则根据pd()函数分组。

法4
np.select()函数:

import numpy as np
import pandas as pd
 
# 创建10000个随机数字
arr = np.random.rand(10000) * 3000
# 定义区间边界值
bins = [0, 50, 100, 1000, np.inf]
# 给区间添加标签
labels = ['0-50', '50-100', '100-1000', '>1000']
# 利用np.select()函数实现分组
conditions = [arr <= 0, (arr > 0) & (arr <= 50), (arr > 50) & (arr <= 100),  (arr > 100) & (arr <= 1000), arr > 1000]
result = np.select(conditions, labels, default='<0')
# 统计每个区间内的数字数量
count = pd.value_counts(result)
# 输出结果
print(count)

该示例使用了np.select()函数,利用多个条件将每个数字分配到对应的标签中,并设置了default参数,当条件都不满足时返回’<0’。最后使用pd.value_counts()函数统计每个区间内数字的数量。

法5
pd.cut()+groupby()函数:

import numpy as np
import pandas as pd

# 创建10000个随机数字
arr = np.random.rand(10000) * 3000
# 定义区间边界值
bins = [0, 50, 100,1000, np.inf]
# 给区间添加标签
labels = ['0-50 '50-100', '100-1000', '>1000']
# 使用pd.cut()函数进行分组
result = pd.cut(arr, bins=bins, labels=labels, right=False)
# 使用groupby()函数进行分组并计数
count = result.groupby(result).size()
# 输出结果
print(count)

该示例直接使用pd.cut()函数对数组进行分组,并设置了right参数为False,表示不包含右边界。然后使用groupby()函数对分组结果进行统计,并输出个区间内的数字数量。

针对Dataframe格式的数据的写法

下面将前面提到的其他 4 种写法应用到 DataFrame 格式的数据中,并返回每组数据的数量值。需要注意的是,除了 pd.cut() 函数,其他函数需要将每个条件赋值给新列,再对新列进行统计。

import numpy as
import pandas as pd
# 创建 DataFrame 格式的数据
df = pd.DataFrame(np.random.rand(10000, 2) * 3000, columns=['col1', 'col2'])
# 定义区间边界值
bins = [0, 50, 100, 1000, np.inf]
# 给区间添加标签
labels = ['0-50', '50-100', '100-1000', '>1000']
# pd.cut()函数分组方法
df['cut_group'] = pd.cut(df['col1'], bins=bins, labels=labels, right=False)
count1 = df['cut_group'].value_counts()
print('cut方法统计结果:\n', count1)
# np.where()函数组方法
df['where_group'] = np.where(df['col1'] <= 0, '<0', pd.cut(df['col1'], bins=bins, labels=labels))
count2 = df['where_group'].value_counts()
print('where方法统计结果:\n', count2)
# np.select()函数分组方法
conditions = [df['col1'] <= 0, (df['col1'] > 0) & (df['col1'] <= 50), (df['col1'] > 50) & (df['col1'] <= 100), (df['col1'] > 100 & (df['col1'] <= 1000), df['col1'] > 100]
choices = ['<0', '0-50', '50-100', '100-1000', '>1000']
df['select_group'] = np.select(conditions, choices, default='<0')
count3 = df['select_group'].value_counts()
print('select方法统计结果:\n', count3)
# apply()函数分组方法
df['apply_group'] = df['col1'].apply(lambda x: labels[bisect.bisect_left(b, x)])
count4 = df['apply_group'].value_counts()
print('apply方法统计结果:\n', count4)

执行以上代码,分别使用了 pd.cut(),np.where(),np.select() 和 apply() 这些方法来统计 col1一列分组后的数据量,各方法的返回值 count1、count2、count3、count4 分别储存在 DataFrame 中。
对于 apply() 方法需要添加 bisect 调用,即 from bisect import bisect。最后使用 print 语句输出各方法的统计结果,类型为 Series。

常见的矢量化操作

  1. apply函数:对数据集中的每一行或应用函数,相较于循环操作可以更高效地执行矢量化函数操作。
  2. groupby函数:根据某一列或多列对数据集进行分组,然后可以应用聚合函数如.mean()、.sum()等计算每组统计量。
  3. merge函数和concat函数:用于组合或合并不同的数据集。
  4. str方法:字符串函数,用于在一列或多列中应用字符串函数。
  5. rolling和expanding函数:用于时间序列数据的聚合运算,例如,移动平均和指数平均。
  6. pd.cut函数和pd.qcut函数:用于将数据离散化,将连续的数据转换成离散的数据,可以用于数据的分析和可视化。
  7. isin函数和str.contains函数:用于根据条件从DataFrame中筛选行或列。
  8. pivot_table函数和melt函数:用于实现长/宽数据格式之间的转换。

补充

  • 数据结构操作:
    append(): 添加一个或多个数据帧或Series到另一个数据帧。
    concat(): 连接多个数据帧或Series。
    merge(): 用于合并数据帧。
    pivot_table(): 创建一个数据透视表。
    stack(): 将数据帧的列堆叠为行。
    unstack(): 将数据帧的行拆分为列。
  • 数据处理操作:
    drop(): 删除数据帧的列或行。
    fillna(): 填充数据帧中的缺失值。
    interpolate(): 插值处理数据帧中的缺失值。
    isna(): 检查数据帧中的值是否为缺失值。
    notna(): 检查数据帧中的值是否不为缺失值。
    replace(): 替换数据帧中的值。
    shift(): 移动数据帧的列。
    roll(): 滚动数据帧的列。
    agg(): 对数据帧的列应用聚合函数。
    apply(): 对数据帧的行或列应用自定义函数。
    transform(): 对数据帧的列应用转换函数。
  • 排序和筛选:
    sort_values(): 按值对数据帧进行排序。
    sort_index(): 按索引对数据帧进行排序。
    groupby(): 对数据帧进行分组。
    filter(): 应用筛选函数。
  • 其他操作:
    assign(): 给数据帧添加新的列。
    astype(): 转换数据帧的列的数据类型。
    itertuples(): 返回一个迭代器,生成数据帧的行。
    loc[]: 通过行和列的标签获取数据。
    iloc[]: 通过整数位置获取数据。

这些操作大多数都是矢量化的,这意味着它们会在整个数据结构上同时应用,而不会逐个处理数据。这种特性使得 Pandas 非常高效,特别是对于大规模的数据处理任务。

  • 16
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是 Python 判断素数的五方法: 1. 蛮力法:从2开始遍历到n-1,如果n能被其中任意一个数整除,则不是素数。 ```python def is_prime(n): if n <= 1: return False for i in range(2, n): if n % i == 0: return False return True ``` 2. 优化的蛮力法:只需要遍历到n的平方根即可。 ```python import math def is_prime(n): if n <= 1: return False for i in range(2, int(math.sqrt(n))+1): if n % i == 0: return False return True ``` 3. 筛法:从2开始,将2的倍数、3的倍数、4的倍数……都标记为合数,最后没有被标记的数即为素数。 ```python def sieve(n): primes = [True] * (n+1) primes[0], primes[1] = False, False for i in range(2, int(math.sqrt(n))+1): if primes[i]: for j in range(i*i, n+1, i): primes[j] = False return primes def is_prime(n): if n <= 1: return False primes = sieve(n) return primes[n] ``` 4. 费马小定理:如果n是素数,那么对于任意a,a^(n-1) mod n = 1。该算法的缺陷是当n不是素数时,结果也可能是1,因此需要进行多次测试。 ```python import random def power(a, n, p): res = 1 while n > 0: if n & 1: res = (res * a) % p a = (a * a) % p n >>= 1 return res def is_prime(n, k=5): if n <= 1 or n == 4: return False if n <= 3: return True for _ in range(k): a = random.randint(2, n-2) if power(a, n-1, n) != 1: return False return True ``` 5. Miller-Rabin算法:该算法是费马小定理的一扩展,可以快速判断一个数是否是合数。该算法的精度可以通过调整参数k来控制,一般取10-20。 ```python import random def power(a, n, p): res = 1 while n > 0: if n & 1: res = (res * a) % p a = (a * a) % p n >>= 1 return res def is_prime(n, k=10): if n <= 1 or n == 4: return False if n <= 3: return True r, d = 0, n-1 while d % 2 == 0: r += 1 d //= 2 for _ in range(k): a = random.randint(2, n-2) x = power(a, d, n) if x == 1 or x == n-1: continue for _ in range(r-1): x = (x * x) % n if x == n-1: break else: return False return True ``` 以上就是 Python 判断素数的五方法,希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值