列を2つに分割しようとしていますが、データにnull値があることがわかっています。このデータフレームを想像してみてください。
df = pd.DataFrame(['fruit: apple','vegetable: asparagus',None, 'fruit: pear'], columns = ['text'])
df
text
0 fruit: apple
1 vegetable: asparagus
2 None
3 fruit: pear
これを次のように複数の列に分割したいと思います。
df['cat'] = df['text'].apply(lambda x: 'unknown' if x == None else x.split(': ')[0])
df['value'] = df['text'].apply(lambda x: 'unknown' if x == None else x.split(': ')[1])
print df
text cat value
0 fruit: apple fruit apple
1 vegetable: asparagus vegetable asparagus
2 None unknown unknown
3 fruit: pear fruit pear
ただし、代わりに次のdfがある場合:
df = pd.DataFrame(['fruit: apple','vegetable: asparagus',np.nan, 'fruit: pear'], columns = ['text'])
分割すると、次のエラーが発生します。
df['cat'] = df['text'].apply(lambda x: 'unknown' if x == np.nan else x.split(': ')[0])
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-159-8e5bca809635> in <module>()
1 df = pd.DataFrame(['fruit: apple','vegetable: asparagus',np.nan, 'fruit: pear'], columns = ['text'])
2 #df.columns = ['col_name']
----> 3 df['cat'] = df['text'].apply(lambda x: 'unknown' if x == np.nan else x.split(': ')[0])
4 df['value'] = df['text'].apply(lambda x: 'unknown' if x == np.nan else x.split(': ')[1])
C:\Python27\lib\site-packages\pandas\core\series.pyc in apply(self, func, convert_dtype, args, **kwds)
2158 values = lib.map_infer(values, lib.Timestamp)
2159
-> 2160 mapped = lib.map_infer(values, f, convert=convert_dtype)
2161 if len(mapped) and isinstance(mapped[0], Series):
2162 from pandas.core.frame import DataFrame
pandas\src\inference.pyx in pandas.lib.map_infer (pandas\lib.c:62187)()
<ipython-input-159-8e5bca809635> in <lambda>(x)
1 df = pd.DataFrame(['fruit: apple','vegetable: asparagus',np.nan, 'fruit: pear'], columns = ['text'])
2 #df.columns = ['col_name']
----> 3 df['cat'] = df['text'].apply(lambda x: 'unknown' if x == np.nan else x.split(': ')[0])
4 df['value'] = df['text'].apply(lambda x: 'unknown' if x == np.nan else x.split(': ')[1])
AttributeError: 'float' object has no attribute 'split'
NaN値で同じ分割を行うにはどうすればよいですか?null値を無視する分割関数を適用するためのより良い方法は一般的にありますか?
これが文字列の例ではなく、次のような場合を想像してみてください。
df = pd.DataFrame([2,4,6,8,10,np.nan,12], columns = ['numerics'])
df['numerics'].apply(lambda x: np.nan if pd.isnull(x) else x/2.0)
Series.applyは、null行をスキップしてnullとして出力するように指示する引数を取る必要があるように感じます。手動でnullを回避せずに、シリーズへの変換を行うためのより一般的な方法は見つかりませんでした。
apply
カスタム関数を使用する代わりに、次のSeries.str.extract
方法を使用できます。
import numpy as np
import pandas as pd
# df = pd.DataFrame(['fruit: apple','vegetable: asparagus',None, 'fruit: pear'],
# columns = ['text'])
df = pd.DataFrame(['fruit: apple','vegetable: asparagus',np.nan, 'fruit: pear'],
columns = ['text'])
df[['cat', 'value']] = df['text'].str.extract(r'([^:]+):?(.*)', expand=True).fillna('unknown')
print(df)
収量
text cat value
0 fruit: apple fruit apple
1 vegetable: asparagus vegetable asparagus
2 NaN unknown unknown
3 fruit: pear fruit pear
apply
カスタム関数を使用すると、一般に、などのベクトル化されたメソッドを使用する同等のコードよりも低速になりますSeries.str.extract
。apply
内部的には、(ベクトル化できない関数を使用して)基本的にPythonのカスタム関数を呼び出しますfor-loop
。
編集された質問について:あなたが持っている場合
df = pd.DataFrame([2,4,6,8,10,np.nan,12], columns = ['numerics'])
次に使用します
In [207]: df['numerics']/2
Out[207]:
0 1.0
1 2.0
2 3.0
3 4.0
4 5.0
5 NaN
6 6.0
Name: numerics, dtype: float64
の代わりに
df['numerics'].apply(lambda x: np.nan if pd.isnull(x) else x/2.0)
繰り返しますapply
が、カスタム関数を使用したベクトル化された算術ビート:
In [210]: df = pd.concat([df]*100, ignore_index=True)
In [211]: %timeit df['numerics']/2
10000 loops, best of 3: 93.8 µs per loop
In [212]: %timeit df['numerics'].apply(lambda x: np.nan if pd.isnull(x) else x/2.0)
1000 loops, best of 3: 836 µs per loop
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加