Pythonでの10進アライメントのフォーマット
-
06-07-2019 - |
質問
これは簡単なはずです 。
これが私の配列です(むしろ、代表的なテスト配列を生成する方法です):
>>> ri = numpy.random.randint
>>> ri2 = lambda x: ''.join(ri(0,9,x).astype('S'))
>>> a = array([float(ri2(x)+ '.' + ri2(y)) for x,y in ri(1,10,(10,2))])
>>> a
array([ 7.99914000e+01, 2.08000000e+01, 3.94000000e+02,
4.66100000e+03, 5.00000000e+00, 1.72575100e+03,
3.91500000e+02, 1.90610000e+04, 1.16247000e+04,
3.53920000e+02])
'\ n'.join(list_o_strings)が出力する文字列のリストが必要です:
79.9914
20.8
394.0
4661.0
5.0
1725.751
391.5
19061.0
11624.7
353.92
左にスペースを置きたい 右に(しかし必要以上に)
小数の後にゼロが必要な場合は、小数の後にゼロが必要です。
科学表記法は必要ありません。
.. and有効数字を失いたくありません。 (353.98000000000002では2は重要ではありません)
ええ、欲しいのはうれしいです。
Python 2.5の%g、%fx.x
などは、私を困惑させているか、できません。
まだ import decimal
を試していません。 NumPy がそれを行うことはわかりません(ただし、 array .__ str __
および array .__ repr __
は10進数に揃えられています(ただし、科学関数を返す場合があります)。
ああ、速度がカウントされます。ここでは大きな配列を扱っています。
現在のソリューションアプローチは次のとおりです。
- str(a)に移動し、NumPyの括弧を解析します
- 配列内の各要素をstr(e)し、split( '。')してからパディングして再構築する
- to a.astype( 'S' + str(i))ここで、iはmax(len(str(a)))であり、パッド
市販のソリューションがあるはずのようです...(しかし必須ではありません)
dtype
がfloat64の場合、上の提案は失敗します:
>>> a
array([ 5.50056103e+02, 6.77383566e+03, 6.01001513e+05,
3.55425142e+08, 7.07254875e+05, 8.83174744e+02,
8.22320510e+01, 4.25076609e+08, 6.28662635e+07,
1.56503068e+02])
>>> ut0 = re.compile(r'(\d)0+)
>>> thelist = [ut0.sub(r'\1', "%12f" % x) for x in a]
>>> print '\n'.join(thelist)
550.056103
6773.835663
601001.513
355425141.8471
707254.875038
883.174744
82.232051
425076608.7676
62866263.55
156.503068
解決
申し訳ありませんが、徹底的な調査の後、最小限の後処理なしで必要なタスクを実行する方法を見つけることができません(不要な末尾のゼロを取り除く)。次のようなもの:
import re
ut0 = re.compile(r'(\d)0+
迅速かつ簡潔ですが、「既製」であるという制約を破ります。 -それは、代わりに、一般的な書式設定(ほとんど必要なことを行いますが、非表示にする末尾のゼロを残します)と望ましくない末尾のゼロを削除するREのモジュール式の組み合わせです。実際には、それはあなたが必要とするものを正確に実行すると思いますが、述べられているようにあなたの条件は、私が信じているように、過度に制約されています。
編集:元の質問が編集され、より重要な数字を指定し、最大数に必要なスペースを超える余分な先行スペースを必要とせず、新しい例を提供します(上の以前の提案では、 tは目的の出力に一致します)。文字列の束に共通する先頭の空白を削除する作業は、 textwrap.dedent -ただし、必要な出力は文字列のリストですが、それは単一の文字列(改行あり)で機能します。問題ありません。行をまとめて、それらをデデントし、再度分割します。
import re
import textwrap
a = [ 5.50056103e+02, 6.77383566e+03, 6.01001513e+05,
3.55425142e+08, 7.07254875e+05, 8.83174744e+02,
8.22320510e+01, 4.25076609e+08, 6.28662635e+07,
1.56503068e+02]
thelist = textwrap.dedent(
'\n'.join(ut0.sub(r'\1', "%20f" % x) for x in a)).splitlines()
print '\n'.join(thelist)
長所:
550.056103
6773.83566
601001.513
355425142.0
707254.875
883.174744
82.232051
425076609.0
62866263.5
156.503068
)
thelist = [ut0.sub(r'\1', "%12f" % x) for x in a]
print '\n'.join(thelist)
迅速かつ簡潔ですが、「既製」であるという制約を破ります。 -それは、代わりに、一般的な書式設定(ほとんど必要なことを行いますが、非表示にする末尾のゼロを残します)と望ましくない末尾のゼロを削除するREのモジュール式の組み合わせです。実際には、それはあなたが必要とするものを正確に実行すると思いますが、述べられているようにあなたの条件は、私が信じているように、過度に制約されています。
編集:元の質問が編集され、より重要な数字を指定し、最大数に必要なスペースを超える余分な先行スペースを必要とせず、新しい例を提供します(上の以前の提案では、 tは目的の出力に一致します)。文字列の束に共通する先頭の空白を削除する作業は、 textwrap.dedent -ただし、必要な出力は文字列のリストですが、それは単一の文字列(改行あり)で機能します。問題ありません。行をまとめて、それらをデデントし、再度分割します。
<*>長所:
<*>他のヒント
Pythonの文字列フォーマットでは、必要な小数のみ(%gを使用)を出力するか、固定の小数セット(%fを使用)を使用できます。ただし、必要な小数のみを印刷する場合は、数値が整数の場合を除き、小数が1つ必要になるため、複雑になります。
これは、次のような結果になることを意味します。
def printarr(arr):
for x in array:
if math.floor(x) == x:
res = '%.1f' % x
else:
res = '%.10g' % x
print "%*s" % (15-res.find('.')+len(res), res)
これは、値が整数の場合は最初に1桁の文字列を作成し、小数でない場合は自動小数点(最大10桁まで)で印刷します。最後に、小数点が揃うように調整して印刷します。
ただし、おそらく、numpyは実際には望みどおりに機能します。通常、長すぎる場合は指数モードにする必要があるためです。