# 将一个系列四舍五入到 N 个有效数字

[英]Round a series to N number of significant figures

``````123.949
23.87
1.9865
0.0129500
``````

``````124.0
23.9
1.99
0.013
``````

``````round(x, N-int(floor(log10(abs(x))))
``````

``````df.col.apply(lambda x: round(x, N - int(floor(log10(abs(x))))))
``````

``````df.applymap(lambda x: round(x, N - int(floor(log10(abs(x))))))
``````

``````import pandas as pd
from math import floor, log10

df = pd.DataFrame({'floats':[123.949, 23.87, 1.9865, 0.0129500]})

def smarter_round(sig):
def rounder(x):
offset = sig - floor(log10(abs(x)))
initial_result = round(x, offset)
if str(initial_result)[-1] == '5' and initial_result == x:
return round(x, offset - 2)
else:
return round(x, offset - 1)
return rounder

print(df['floats'].apply(smarter_round(3)))

Out:
0    124.000
1     23.900
2      1.990
3      0.013
Name: floats, dtype: float64
``````

``````from typing import Union
import pandas as pd
import numpy as np

def significant_digits(df: Union[pd.DataFrame, pd.Series],
significance: int,
inplace: bool = False) -> Union[pd.DataFrame, pd.Series, None]:

# Create a positive data vector with a place holder for NaN / inf data
data = df.values
data_positive = np.where(np.isfinite(data) & (data != 0), np.abs(data), 10**(significance-1))

# Align data by magnitude, round, and scale back to original
magnitude = 10 ** (significance - 1 - np.floor(np.log10(data_positive)))
data_rounded = np.round(data * magnitude) / magnitude

# Place back into Series or DataFrame
if inplace:
df.loc[:] = data_rounded
else:
if isinstance(df, pd.DataFrame):
return pd.DataFrame(data=data_rounded, index=df.index, columns=df.columns)
else:
return pd.Series(data=data_rounded, index=df.index)
``````