将 Dataframe 列值转换为公共小数位
Convert Dataframe column values to common decimal place
我有一个 Pandas 数据框,看起来像这样。
CustId CustName Price_1 Priceqty1 Price_2 Priceqty2 Price_3 Priceqty3 Price_4 Price_5
5015 Axn 315.12 1 374 1 126.32 3 167.8765
5015 Axn 75.36 3 190.19 7 33.16 1 190.19 88
5015 Axn 123 5 4 18.07 2 0.073 12
7315 Bxy 12.0 4 22.345 3 77.89 1 345.0 3344
7315 Bxy 987.90 7 34.06 4 90.09 3 876.34 908.76
3283 Cxz 123.34 8 55.78 7 12 9 878.09 98.456
3283 Cxz 178.90 7 88 8 0.09 0 987.56
我有 5 个不同的价格列,它们具有不同的值和不同的小数位。为了让最终用户更好地理解,我需要将所有价格列值转换为通用小数位。
要转换我需要遵循一定的规则:
1.conversion 应该分别为每个客户 ID 完成。
2.Common 小数位将由具有最大小数位的价格列值确定。
让我们以 CustId 5015 为例
CustId CustName Price_1 Priceqty1 Price_2 Priceqty2 Price_3 Priceqty3 Price_4 Price_5
5015 Axn 315.12 1 374 1 126.32 3 167.8765
5015 Axn 75.36 3 190.19 7 33.16 1 190.19 88
5015 Axn 123 5 4 18.07 2 0.073 12
如果你看到你可以找到 Price_4 列的第一行,这里的值为 167.8765,小数位是 4 。如果您检查 Custid 5015 的所有价格列值,与其他价格列值相比,小数位 4 是最大的。因为 4 是最大的,所以我需要将 custid 5015 的每个价格列值转换为小数点后 4 位。
转换后应该是这样的。
CustId CustName Price_1 Priceqty1 Price_2 Priceqty2 Price_3 Priceqty3 Price_4 Price_5
5015 Axn 315.1200 1 374.0000 1 126.3200 3 167.8765
5015 Axn 75.3600 3 190.1900 7 33.1600 1 190.1900 88
5015 Axn 123.0000 5 4 18.0700 2 0.0730 12
与 custid 5015 类似,custid 7315 的最大十进制值为 3
CustId CustName Price_1 Priceqty1 Price_2 Priceqty2 Price_3 Priceqty3 Price_4 Price_5
7315 Bxy 12.000 4 22.345 3 77.890 1 345.000 3344.000
7315 Bxy 987.900 7 34.060 4 90.090 3 876.340 908.760
空白值只能为空白。
我需要为每个 custid 执行此操作,有 800 多个不同的客户 ID。最有效的方法是什么?
您可以先计算数字的整数和小数部分长度,然后取最大值:
lengths = (df.filter(like='Price_')
.stack().astype(str).dropna()
.str.split('.', expand=True).astype(str)
.apply(lambda c: c.str.len())
.max()
)
输出:
0 4 # this is the integer part
1 4 # this is the decimal part
然后,如果您不想更改数据而只想打印数据帧:
integer, decimal = lengths.values
total = integer+decimal+1
custom_format = '{:%s.%sf}' % (total,decimal)
pd.options.display.float_format = custom_format.format
print(df.fillna(''))
输出:
CustId CustName Price_1 Priceqty1 Price_2 Priceqty2 Price_3 Priceqty3 Price_4 Price_5
0 5015 Axn 315.1200 1 374.0000 1.0000 126.3200 3.0000 167.8765
1 5015 Axn 75.3600 3 190.1900 7.0000 33.1600 1.0000 190.1900 88.0000
2 5015 Axn 123.0000 5 4.0000 18.0700 2.0000 0.0730 12.0000
3 7315 Bxy 12.0000 4 22.3450 3.0000 77.8900 1.0000 345.0000 3344.0000
4 7315 Bxy 987.9000 7 34.0600 4.0000 90.0900 3.0000 876.3400 908.7600
5 3283 Cxz 123.3400 8 55.7800 7.0000 12.0000 9.0000 878.0900 98.4560
6 3283 Cxz 178.9000 7 88.0000 8.0000 0.0900 0.0000 987.5600
df = df.fillna('')
m = df.filter(regex='Price_').astype(str).applymap(lambda x: len(x.split('.')[1]) if x else 0).max().max()
pd.options.display.float_format = ('{:,.' + str(m) + 'f}').format # based on
print(df)
打印:
CustId CustName Price_1 Priceqty1 ... Price_3 Priceqty3 Price_4 Price_5
0 5015 Axn 315.1200 1 ... 126.3200 3 167.8764
1 5015 Axn 75.3600 3 ... 33.1600 1 190.1900 88.0000
2 5015 Axn 123.0000 5 ... 18.0700 2 0.0730 12.0000
3 7315 Bxy 12.0000 4 ... 77.8900 1 345.0000 3,344.0000
4 7315 Bxy 987.9000 7 ... 90.0900 3 876.3400 908.7600
5 3283 Cxz 123.3400 8 ... 12.0000 9 878.0900 98.4560
6 3283 Cxz 178.9000 7 ... 0.0900 0 987.5600
[7 rows x 10 columns]
每组使用自定义函数:
def f(x):
#get string with maximal values after '.'
a = max([str(y).split('.')[1] for y in np.ravel(x) if pd.notna(y)], key=len)
#set format of floats
return x.applymap(lambda x: f'{x:.{len(a)}f}').replace('nan','')
df1 = df.filter(like='Price_')
df[df1.columns] = df1.groupby(df['CustId']).apply(f)
print (df)
CustId CustName Price_1 Priceqty1 Price_2 Priceqty2 Price_3 \
0 5015 Axn 315.1200 1 374.0000 1.00 126.3200
1 5015 Axn 75.3600 3 190.1900 7.00 33.1600
2 5015 Axn 123.0000 5 4.0000 18.07 2.0000
3 7315 Bxy 12.000 4 22.345 3.00 77.890
4 7315 Bxy 987.900 7 34.060 4.00 90.090
5 3283 Cxz 123.340 8 55.780 7.00 12.000
6 3283 Cxz 178.900 7 88.000 8.00 0.090
Priceqty3 Price_4 Price_5
0 3.000 167.8765
1 1.000 190.1900 88.0000
2 0.073 12.0000
3 1.000 345.000 3344.000
4 3.000 876.340 908.760
5 9.000 878.090 98.456
6 0.000 987.560
我有一个 Pandas 数据框,看起来像这样。
CustId CustName Price_1 Priceqty1 Price_2 Priceqty2 Price_3 Priceqty3 Price_4 Price_5
5015 Axn 315.12 1 374 1 126.32 3 167.8765
5015 Axn 75.36 3 190.19 7 33.16 1 190.19 88
5015 Axn 123 5 4 18.07 2 0.073 12
7315 Bxy 12.0 4 22.345 3 77.89 1 345.0 3344
7315 Bxy 987.90 7 34.06 4 90.09 3 876.34 908.76
3283 Cxz 123.34 8 55.78 7 12 9 878.09 98.456
3283 Cxz 178.90 7 88 8 0.09 0 987.56
我有 5 个不同的价格列,它们具有不同的值和不同的小数位。为了让最终用户更好地理解,我需要将所有价格列值转换为通用小数位。
要转换我需要遵循一定的规则: 1.conversion 应该分别为每个客户 ID 完成。 2.Common 小数位将由具有最大小数位的价格列值确定。
让我们以 CustId 5015 为例
CustId CustName Price_1 Priceqty1 Price_2 Priceqty2 Price_3 Priceqty3 Price_4 Price_5
5015 Axn 315.12 1 374 1 126.32 3 167.8765
5015 Axn 75.36 3 190.19 7 33.16 1 190.19 88
5015 Axn 123 5 4 18.07 2 0.073 12
如果你看到你可以找到 Price_4 列的第一行,这里的值为 167.8765,小数位是 4 。如果您检查 Custid 5015 的所有价格列值,与其他价格列值相比,小数位 4 是最大的。因为 4 是最大的,所以我需要将 custid 5015 的每个价格列值转换为小数点后 4 位。
转换后应该是这样的。
CustId CustName Price_1 Priceqty1 Price_2 Priceqty2 Price_3 Priceqty3 Price_4 Price_5
5015 Axn 315.1200 1 374.0000 1 126.3200 3 167.8765
5015 Axn 75.3600 3 190.1900 7 33.1600 1 190.1900 88
5015 Axn 123.0000 5 4 18.0700 2 0.0730 12
与 custid 5015 类似,custid 7315 的最大十进制值为 3
CustId CustName Price_1 Priceqty1 Price_2 Priceqty2 Price_3 Priceqty3 Price_4 Price_5
7315 Bxy 12.000 4 22.345 3 77.890 1 345.000 3344.000
7315 Bxy 987.900 7 34.060 4 90.090 3 876.340 908.760
空白值只能为空白。
我需要为每个 custid 执行此操作,有 800 多个不同的客户 ID。最有效的方法是什么?
您可以先计算数字的整数和小数部分长度,然后取最大值:
lengths = (df.filter(like='Price_')
.stack().astype(str).dropna()
.str.split('.', expand=True).astype(str)
.apply(lambda c: c.str.len())
.max()
)
输出:
0 4 # this is the integer part
1 4 # this is the decimal part
然后,如果您不想更改数据而只想打印数据帧:
integer, decimal = lengths.values
total = integer+decimal+1
custom_format = '{:%s.%sf}' % (total,decimal)
pd.options.display.float_format = custom_format.format
print(df.fillna(''))
输出:
CustId CustName Price_1 Priceqty1 Price_2 Priceqty2 Price_3 Priceqty3 Price_4 Price_5
0 5015 Axn 315.1200 1 374.0000 1.0000 126.3200 3.0000 167.8765
1 5015 Axn 75.3600 3 190.1900 7.0000 33.1600 1.0000 190.1900 88.0000
2 5015 Axn 123.0000 5 4.0000 18.0700 2.0000 0.0730 12.0000
3 7315 Bxy 12.0000 4 22.3450 3.0000 77.8900 1.0000 345.0000 3344.0000
4 7315 Bxy 987.9000 7 34.0600 4.0000 90.0900 3.0000 876.3400 908.7600
5 3283 Cxz 123.3400 8 55.7800 7.0000 12.0000 9.0000 878.0900 98.4560
6 3283 Cxz 178.9000 7 88.0000 8.0000 0.0900 0.0000 987.5600
df = df.fillna('')
m = df.filter(regex='Price_').astype(str).applymap(lambda x: len(x.split('.')[1]) if x else 0).max().max()
pd.options.display.float_format = ('{:,.' + str(m) + 'f}').format # based on
print(df)
打印:
CustId CustName Price_1 Priceqty1 ... Price_3 Priceqty3 Price_4 Price_5
0 5015 Axn 315.1200 1 ... 126.3200 3 167.8764
1 5015 Axn 75.3600 3 ... 33.1600 1 190.1900 88.0000
2 5015 Axn 123.0000 5 ... 18.0700 2 0.0730 12.0000
3 7315 Bxy 12.0000 4 ... 77.8900 1 345.0000 3,344.0000
4 7315 Bxy 987.9000 7 ... 90.0900 3 876.3400 908.7600
5 3283 Cxz 123.3400 8 ... 12.0000 9 878.0900 98.4560
6 3283 Cxz 178.9000 7 ... 0.0900 0 987.5600
[7 rows x 10 columns]
每组使用自定义函数:
def f(x):
#get string with maximal values after '.'
a = max([str(y).split('.')[1] for y in np.ravel(x) if pd.notna(y)], key=len)
#set format of floats
return x.applymap(lambda x: f'{x:.{len(a)}f}').replace('nan','')
df1 = df.filter(like='Price_')
df[df1.columns] = df1.groupby(df['CustId']).apply(f)
print (df)
CustId CustName Price_1 Priceqty1 Price_2 Priceqty2 Price_3 \
0 5015 Axn 315.1200 1 374.0000 1.00 126.3200
1 5015 Axn 75.3600 3 190.1900 7.00 33.1600
2 5015 Axn 123.0000 5 4.0000 18.07 2.0000
3 7315 Bxy 12.000 4 22.345 3.00 77.890
4 7315 Bxy 987.900 7 34.060 4.00 90.090
5 3283 Cxz 123.340 8 55.780 7.00 12.000
6 3283 Cxz 178.900 7 88.000 8.00 0.090
Priceqty3 Price_4 Price_5
0 3.000 167.8765
1 1.000 190.1900 88.0000
2 0.073 12.0000
3 1.000 345.000 3344.000
4 3.000 876.340 908.760
5 9.000 878.090 98.456
6 0.000 987.560