簡體   English   中英

將未知整數舍入到最高 base10 值 Python

[英]Round unknown whole number to highest base10 value Python

值將作為來自 pandas 數據幀的 max() 給出。 對於每個項目,我想獲得一個四舍五入的最大值來為 matplot plot 創建 y 刻度,刻度數 = 10。

我使用的數據框是官方的 John Hopkins Covid Data。 前面的代碼返回按國家或州、每日總數或累計、病例或死亡分類的數據框。

我在 for 循環中編寫了代碼,該代碼將轉換最大值(可能超過 2000 萬或低至 6)以獲取前導數字並加 1,然后在需要時連接額外的零。 如果下一個數字很小,我寧願將值向下舍入,因為此代碼會在某些圖表的頂部產生小間隙。

我寫的代碼是在str和int pythonic之間來回轉換的嗎? 有沒有一種簡單的方法可以向該代碼添加一個圓形方法? 或者是否有更好、更有效的方法來做我想做的事情?

# Per Capita ## (identical version for daily totals on dfs1)
cumulative2 = dfs2.T[default[ind]]
daily_cases2 = cumulative2.diff()
d_max2 = daily_cases2.max().max()
c_max2 = cumulative2.max().max()

...

plot1 = daily_cases1.plot(kind='area', stacked=False, ax=ax1, lw=2, ylim=(0, d_max1))
plot2 = daily_cases2.plot(kind='area', stacked=False, ax=ax2, lw=2, ylim=(0, d_max2))
plot3 = cumulative1.plot(kind='area', stacked=False, ax=ax3, lw=2, ylim=(0, c_max1))
plot4 = cumulative2.plot(kind='area', stacked=False, ax=ax4, lw=2, ylim=(0, c_max2))

plots = [plot1, plot2, plot3, plot4]
maxes = [d_max1, d_max2, c_max1, c_max2]
for i, plot in enumerate(plots):
    rnd_max = int(f'{str(int(str(int(maxes[i]))[0]) + 1) + "0" * (len(str(int(maxes[i]))) - 1)}')
    yticks = np.arange(0, rnd_max, 1 if rnd_max < 10 else rnd_max // 10)
    ytick_labels = pd.Series(yticks).apply(lambda value: f"{int(value):,}")
    plot.set_yticks(yticks)
    plot.set_yticklabels(ytick_labels)

編輯:如果值為 2,750,00,我希望為 3,如果值為 41,則為 4。所以不是真正的以 10 為底的回報。 但以 10 為底,以前導數字為基數。

累積:

State    California  Arizona  Florida  New York    Texas  Illinois
11/4/20      950920   250633   821123    519890  1003342    443803
3/14/20         372       12       76       557       60        64
5/22/20       90281    15624    49451    360818    53817    105444

日常的:

State    California  Arizona  Florida  New York    Texas  Illinois
4/3/20       1226.0    173.0   1260.0   10675.0    771.0    1209.0
6/25/20      5088.0   3091.0   5004.0     814.0   5787.0     894.0
11/3/20      4990.0   1679.0   4637.0    2069.0   9721.0    6516.0

c_max 和 d_max 只是浮點數/整數列表(等於正在繪制的 pd 系列的最大值)63817.0

2675262

這是一系列情節的output。 您可以看到第一個圖表的刻度 go 遠高於第一個圖表的實際最大值(忽略 plot 的位置,它現在是最合適的)。 這是我想減輕的將低數字四舍五入的結果。 但我們的目標是提供最干凈的刻度值,同時保持情節的美觀和緊湊

一系列地塊中的 1 個

如果你真的只想要你的 10 步的一個有效數字,你可以用使用以 10 為底的對數的東西來復制你的(不,不是真正的 Pythonic)字符串轉換表達式,例如

def round10(n):
  return 10**math.ceil(math.log10(n))

但是正如您自己注意到的那樣,這並不會真正產生有用的結果,例如,如果最大值為 1001,則 y 刻度將 go 從 0 到 10000,這意味着所有內容基本上都會被壓縮到最近的刻度。 內置的自動縮放功能更加復雜,並最大限度地增加了可用區域。

from math import floor, log
def round_first(x):
    p = 10**floor(log(x,10))
    return (round(x/p)*p)
>>> round_first(5123)
5000
>>> round_first(5987)
6000
>>>

編輯:如果您關心性能,則將所有數據作為 numpy arrays 並執行矢量化方法。 下面的代碼是矢量化的,也不會因零或負數而窒息。

import numpy as np
>>> def round_first(x):                                 
...     xa = np.abs(x)                                  
...     xs = np.sign(x)                                 
...     nonzero = x!=0                                  
...     p=10**np.floor(np.log10(xa[nonzero]))           
...     out=np.zeros(x.shape)
...     out[nonzero] = np.round(xa[nonzero]/p)*p*xs[nonzero]
...     return out                                      
...
>>> x = np.arange(-1000,2001,67)                        
>>> x
array([-1000,  -933,  -866,  -799,  -732,  -665,  -598,  -531,  -464,
        -397,  -330,  -263,  -196,  -129,   -62,     5,    72,   139,
         206,   273,   340,   407,   474,   541,   608,   675,   742,
         809,   876,   943,  1010,  1077,  1144,  1211,  1278,  1345,
        1412,  1479,  1546,  1613,  1680,  1747,  1814,  1881,  1948])
>>> round_first(x)
array([-1000.,  -900.,  -900.,  -800.,  -700.,  -700.,  -600.,  -500.,
        -500.,  -400.,  -300.,  -300.,  -200.,  -100.,   -60.,     5.,
          70.,   100.,   200.,   300.,   300.,   400.,   500.,   500.,
         600.,   700.,   700.,   800.,   900.,   900.,  1000.,  1000.,
        1000.,  1000.,  1000.,  1000.,  1000.,  1000.,  2000.,  2000.,
        2000.,  2000.,  2000.,  2000.,  2000.])

此外,您的問題是最接近的(您說 41 變為 40 而不是 50),但您對自己的自我回答使用 ceil(),這將使 41 go 變為 50。

def round10_first(x):
    from math import floor, ceil, log
    p = 10 ** floor(log(x, 10))
    return ceil(x / p) * p

謝謝你們的幫助。 實際上,我將您的答案結合起來作為我的解決方案我在它們上運行了一個 timeit,它們的速度相同,但我將使用您構建的那個更 Pythonic

%timeit -n 10000000 function1
%timeit -n 10000000 function2

16.7 ns ± 0.108 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
16.8 ns ± 0.13 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM