PandasでPython 0.19.1
を使用しています。3.これらのコード行で警告が表示されます。文字列Peter
が列Unnamed: 5
にあるすべての行番号を含むリストを取得しようとしています。
df = pd.read_Excel(xls_path)
myRows = df[df['Unnamed: 5'] == 'Peter'].index.tolist()
警告:
"\Python36\lib\site-packages\pandas\core\ops.py:792: FutureWarning: elementwise
comparison failed; returning scalar, but in the future will perform
elementwise comparison
result = getattr(x, name)(y)"
このFutureWarningとは何ですか。それが機能しているように見えるので無視してください。
このFutureWarningはPandasのものではなく、numpyのものであり、バグはmatplotlibなどにも影響します。トラブルの原因により近い警告を再現する方法は次のとおりです:
import numpy as np
print(np.__version__) # Numpy version '1.12.0'
'x' in np.arange(5) #Future warning thrown here
FutureWarning: elementwise comparison failed; returning scalar instead, but in the
future will perform elementwise comparison
False
Double equals演算子を使用してこのバグを再現する別の方法:
import numpy as np
np.arange(5) == np.arange(5).astype(str) #FutureWarning thrown here
振動プロット実装の下でこのFutureWarningの影響を受けるMatplotlibの例: https://matplotlib.org/examples/pylab_examples/quiver_demo.html
Numpyとネイティブpythonの間には、文字列をnumpyの数値型と比較したときに何が起こるかについて意見の相違があります。左のオペランドはpythonの芝、プリミティブ文字列であり、中央の操作はpythonの芝ですが、右のオペランドはnumpyの芝です。 PythonスタイルのスカラーまたはブールのNumpyスタイルのndarrayを返す必要がありますか? Numpyは、boolのndarrayについて、Pythonの開発者は同意しません。古典的なスタンドオフ。
アイテムが配列に存在する場合、要素ごとの比較またはスカラーにする必要がありますか?
コードまたはライブラリがpython文字列をnumpy ndarrayと比較するためにin
または==
演算子を使用している場合、互換性がないため、試してみると、スカラー、ただし今のところのみ。この警告は、将来この動作が変わる可能性があることを示しているため、python/numpyがNumpyスタイルを採用することを決定した場合、コードはじゅうぶんに流されます。
NumpyとPythonはスタンドオフ状態にあり、現時点では操作はスカラーを返しますが、将来的には変更される可能性があります。
https://github.com/numpy/numpy/issues/6784
https://github.com/pandas-dev/pandas/issues/78
pythonとnumpyのバージョンをロックダウンし、警告を無視して動作が変わらないことを期待するか、==
とin
の左右両方のオペランドをnumpyから変換します。型またはプリミティブpython数値型。
警告をグローバルに抑制します。
import warnings
import numpy as np
warnings.simplefilter(action='ignore', category=FutureWarning)
print('x' in np.arange(5)) #returns False, without Warning
行ごとに警告を抑制します。
import warnings
import numpy as np
with warnings.catch_warnings():
warnings.simplefilter(action='ignore', category=FutureWarning)
print('x' in np.arange(2)) #returns False, warning is suppressed
print('x' in np.arange(10)) #returns False, Throws FutureWarning
名前で警告を抑制し、pythonの現在のバージョンとnumpyについて言及する大きなコメントを横に付けて、このコードは壊れやすく、これらのバージョンが必要であると言って、ここにリンクを張ってください。缶を蹴ってください。
TLDR:pandas
はジェダイです。 numpy
は小屋です。 python
は銀河帝国です。 https://youtu.be/OZczsiCfQQk?t=
index_col
ファイルの読み取りをPanda
のデータフレームに設定しようとすると、同じエラーが発生します。
df = pd.read_csv('my_file.tsv', sep='\t', header=0, index_col=['0']) ## or same with the following
df = pd.read_csv('my_file.tsv', sep='\t', header=0, index_col=[0])
以前にそのようなエラーに遭遇したことはありません。私はまだこの背後にある理由を解明しようとしています(@Eric Leschinskiの説明などを使用)。
とにかく、私は理由を理解するまで、次のアプローチは今のところ問題を解決します:
df = pd.read_csv('my_file.tsv', sep='\t', header=0) ## not setting the index_col
df.set_index(['0'], inplace=True)
このような動作の理由がわかり次第、これを更新します。
同じ警告メッセージに対する私の経験は、TypeErrorが原因でした。
TypeError:無効な型比較
そのため、Unnamed: 5
のデータ型を確認することをお勧めします
for x in df['Unnamed: 5']:
print(type(x)) # are they 'str' ?
警告メッセージを複製する方法は次のとおりです。
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(3, 2), columns=['num1', 'num2'])
df['num3'] = 3
df.loc[df['num3'] == '3', 'num3'] = 4 # TypeError and the Warning
df.loc[df['num3'] == 3, 'num3'] = 4 # No Error
それが役に立てば幸い。
これに対する簡単な回避策は、numpy.core.defchararray
を使用することです。私も同じ警告メッセージに直面し、上記のモジュールを使用してそれを解決することができました。
import numpy.core.defchararray as npd
resultdataset = npd.equal(dataset1, dataset2)
列にヌル文字列が含まれていると思っていたため、この警告が表示されましたが、チェックするとnp.nanが含まれていました。
if df['column'] == '':
列を空の文字列に変更すると助けになりました:)
パンダ、いくつかのnumpyメソッド、リスト内包メソッドなど、これを行うために可能なメソッドのいくつかを比較しました。
まず、ベースラインから始めましょう:
>>> import numpy as np
>>> import operator
>>> import pandas as pd
>>> x = [1, 2, 1, 2]
>>> %time count = np.sum(np.equal(1, x))
>>> print("Count {} using numpy equal with ints".format(count))
CPU times: user 52 µs, sys: 0 ns, total: 52 µs
Wall time: 56 µs
Count 2 using numpy equal with ints
したがって、ベースラインはカウントが正しい2
である必要があり、50 us
について取る必要があります。
次に、単純な方法を試します。
>>> x = ['s', 'b', 's', 'b']
>>> %time count = np.sum(np.equal('s', x))
>>> print("Count {} using numpy equal".format(count))
CPU times: user 145 µs, sys: 24 µs, total: 169 µs
Wall time: 158 µs
Count NotImplemented using numpy equal
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/ipykernel_launcher.py:1: FutureWarning: elementwise comparison failed; returning scalar instead, but in the future will perform elementwise comparison
"""Entry point for launching an IPython kernel.
そして、ここでは、間違った答え(NotImplemented != 2
)が返され、長い時間がかかり、警告がスローされます。
そこで、別の単純な方法を試します。
>>> %time count = np.sum(x == 's')
>>> print("Count {} using ==".format(count))
CPU times: user 46 µs, sys: 1 µs, total: 47 µs
Wall time: 50.1 µs
Count 0 using ==
再び、間違った答え(0 != 2
)。後続の警告がないため、これはさらに潜行性があります(0
は2
と同様に渡すことができます)。
それでは、リストの理解を試みましょう。
>>> %time count = np.sum([operator.eq(_x, 's') for _x in x])
>>> print("Count {} using list comprehension".format(count))
CPU times: user 55 µs, sys: 1 µs, total: 56 µs
Wall time: 60.3 µs
Count 2 using list comprehension
ここで正しい答えが得られ、それは非常に高速です!
別の可能性、pandas
:
>>> y = pd.Series(x)
>>> %time count = np.sum(y == 's')
>>> print("Count {} using pandas ==".format(count))
CPU times: user 453 µs, sys: 31 µs, total: 484 µs
Wall time: 463 µs
Count 2 using pandas ==
遅いが、正しい!
最後に、使用するオプション:numpy
配列をobject
型にキャストします。
>>> x = np.array(['s', 'b', 's', 'b']).astype(object)
>>> %time count = np.sum(np.equal('s', x))
>>> print("Count {} using numpy equal".format(count))
CPU times: user 50 µs, sys: 1 µs, total: 51 µs
Wall time: 55.1 µs
Count 2 using numpy equal
早くて正しい!
配列が大きすぎない場合、または配列が多すぎない場合は、==
の左側を強制的に文字列にすることで回避できる場合があります。
myRows = df[str(df['Unnamed: 5']) == 'Peter'].index.tolist()
しかし、これはdf['Unnamed: 5']
が文字列の場合は約1.5倍、df['Unnamed: 5']
が小さなnumpy配列(長さ= 10)の場合は25-30倍遅く、numpy配列の場合は150-160倍遅くなります。長さ100(500回の試行の平均)。
a = linspace(0, 5, 10)
b = linspace(0, 50, 100)
n = 500
string1 = 'Peter'
string2 = 'blargh'
times_a = zeros(n)
times_str_a = zeros(n)
times_s = zeros(n)
times_str_s = zeros(n)
times_b = zeros(n)
times_str_b = zeros(n)
for i in range(n):
t0 = time.time()
tmp1 = a == string1
t1 = time.time()
tmp2 = str(a) == string1
t2 = time.time()
tmp3 = string2 == string1
t3 = time.time()
tmp4 = str(string2) == string1
t4 = time.time()
tmp5 = b == string1
t5 = time.time()
tmp6 = str(b) == string1
t6 = time.time()
times_a[i] = t1 - t0
times_str_a[i] = t2 - t1
times_s[i] = t3 - t2
times_str_s[i] = t4 - t3
times_b[i] = t5 - t4
times_str_b[i] = t6 - t5
print('Small array:')
print('Time to compare without str conversion: {} s. With str conversion: {} s'.format(mean(times_a), mean(times_str_a)))
print('Ratio of time with/without string conversion: {}'.format(mean(times_str_a)/mean(times_a)))
print('\nBig array')
print('Time to compare without str conversion: {} s. With str conversion: {} s'.format(mean(times_b), mean(times_str_b)))
print(mean(times_str_b)/mean(times_b))
print('\nString')
print('Time to compare without str conversion: {} s. With str conversion: {} s'.format(mean(times_s), mean(times_str_s)))
print('Ratio of time with/without string conversion: {}'.format(mean(times_str_s)/mean(times_s)))
結果:
Small array:
Time to compare without str conversion: 6.58464431763e-06 s. With str conversion: 0.000173756599426 s
Ratio of time with/without string conversion: 26.3881526541
Big array
Time to compare without str conversion: 5.44309616089e-06 s. With str conversion: 0.000870866775513 s
159.99474375821288
String
Time to compare without str conversion: 5.89370727539e-07 s. With str conversion: 8.30173492432e-07 s
Ratio of time with/without string conversion: 1.40857605178