从数据框中的数字中提取最高位值数字

Extract the highest place value digit from numbers in a dataframe

我有一个 python 数据框,其中有一列名为错误代码:

df1=pd.DataFrame({'errorcodes1':[6321,235,314,421,5346,514,4,3415,136,216,34,623])

我需要一个输出的函数:[6,2,3,4,5,5,4,3,1,2,3,6]。

我想到了把每个错误码都转成字符串,然后提取元素[0]。但是,这涉及字符串操作,从整数转换为整数,这可能很慢。有没有更快的方法?

我认为字符串操作是最好的,或者你可以尝试按长度划分每个数据单元

如果您被禁止转换为 str,您可以通过以下方式利用布里格斯对数来完成该任务:

import math
numbers = [6321,235,314,421,5346,514,4,3415,136,216,34,623]
def first_digit(n):
    return n//10**int(math.log(n, 10))
for n in numbers:
    print(n, first_digit(n), sep='\t')

输出:

6321    6
235 2
314 3
421 4
5346    5
514 5
4   4
3415    3
136 1
216 2
34  3
623 6

说明:首先我使用前面提到的对数检测数字中的位数,然后我使用整数除法 (//) 检查给定数字中有多少 10**(number_of_digits)

我测试了哪种方法更快 - logstr - 两者给出的结果相似但 str 稍快一些。如果您不将 str 转换为 int 那么它会更快。您也可以使用 ord() 而不是 int() 来使其更快。

e1 = time.time()
results = [int(str(n)[0]) for n in numbers]
e2 = time.time()
print('int(str): {:.10f}'.format(e2-e1))

e1 = time.time()
results = [n//10**int(math.log(n, 10)) for n in numbers]
e2 = time.time()
print('     log: {:.10f}'.format(e2-e1))

e1 = time.time()
results = [str(n)[0] for n in numbers]
e2 = time.time()
print('     str: {:.10f}'.format(e2-e1))

e1 = time.time()
results = [ord(str(n)[0])-ord('0') for n in numbers]
e2 = time.time()
print('ord(str): {:.10f}'.format(e2-e1))

结果

int(str): 0.0000424385
     log: 0.0000514984
     str: 0.0000197887
ord(str): 0.0000286102

为了进行更好的测试,我使用了模块 timeit,它多次运行代码并计算平均时间。

我还使用 df.apply() 检查代码,将 df 转换为 list,然后将 list 转换为 df。所有显示用于获取第一个数字的时间非常小,因此在所有计算中都不重要

import pandas as pd
import math
import time
import timeit

def test1():
    results = [int(str(n)[0]) for n in numbers]

def test1b():
    results = [ord(str(n)[0]) - ord('0') for n in numbers]

def test1c():
    results = [str(n)[0] for n in numbers]

def test2():
    results = [n//10**int(math.log(n, 10)) for n in numbers]

def test3():
    df['number'] = df['errorcodes1'].apply(lambda n:int(str(n)[0]))

def test3b():
    df['number'] = df['errorcodes1'].apply(lambda n:ord(str(n)[0])-ord('0'))

def test3c():
    df['number'] = df['errorcodes1'].apply(lambda n:str(n)[0])

def test4():    
    df['number'] = df['errorcodes1'].apply(lambda n:n//10**int(math.log(n, 10)))

def test5():
    numbers = df['errorcodes1'].to_list()
    results = [int(str(n)[0]) for n in numbers]
    df['number'] = results

def test6():
    numbers = df['errorcodes1'].to_list()
    results = [n//10**int(math.log(n, 10)) for n in numbers]
    df['number'] = results

df = pd.DataFrame({'errorcodes1':[6321,235,314,421,5346,514,4,3415,136,216,34,623]})
numbers = df['errorcodes1'].to_list()

print('list log()      : {:.5f}'.format(timeit.timeit(test2, number=1000)))
print('list int(str()) : {:.5f}'.format(timeit.timeit(test1, number=1000)))
print('list ord(str()) : {:.5f}'.format(timeit.timeit(test1b, number=1000)))
print('list str()      : {:.5f}'.format(timeit.timeit(test1c, number=1000)))
print('---')
print('df.apply(log())      : {:.5f}'.format(timeit.timeit(test4, number=1000)))
print('df.apply(int(str())) : {:.5f}'.format(timeit.timeit(test3, number=1000)))
print('df.apply(ord(str())) : {:.5f}'.format(timeit.timeit(test3b, number=1000)))
print('df.apply(str())      : {:.5f}'.format(timeit.timeit(test3c, number=1000)))
print('---')
print('df -> list int(str()) -> df : {:.5f}'.format(timeit.timeit(test5, number=1000)))
print('df -> list log()      -> df : {:.5f}'.format(timeit.timeit(test6, number=1000)))

结果:

list log()      : 0.01505
list int(str()) : 0.00917
list ord(str()) : 0.00713
list str()      : 0.00463
---
df.apply(log())      : 0.62433
df.apply(int(str())) : 0.61940
df.apply(ord(str())) : 0.60435
df.apply(str())      : 0.64205
---
df -> list int(str()) -> df : 0.27188
df -> list log()      -> df : 0.27696