42

st複数の列を含むpandas DataFrame があります。

<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 53732 entries, 1993-01-07 12:23:58 to 2012-12-02 20:06:23
Data columns:
Date(dd-mm-yy)_Time(hh-mm-ss)       53732  non-null values
Julian_Day                          53732  non-null values
AOT_1020                            53716  non-null values
AOT_870                             53732  non-null values
AOT_675                             53188  non-null values
AOT_500                             51687  non-null values
AOT_440                             53727  non-null values
AOT_380                             51864  non-null values
AOT_340                             52852  non-null values
Water(cm)                           51687  non-null values
%TripletVar_1020                    53710  non-null values
%TripletVar_870                     53726  non-null values
%TripletVar_675                     53182  non-null values
%TripletVar_500                     51683  non-null values
%TripletVar_440                     53721  non-null values
%TripletVar_380                     51860  non-null values
%TripletVar_340                     52846  non-null values
440-870Angstrom                     53732  non-null values
380-500Angstrom                     52253  non-null values
440-675Angstrom                     53732  non-null values
500-870Angstrom                     53732  non-null values
340-440Angstrom                     53277  non-null values
Last_Processing_Date(dd/mm/yyyy)    53732  non-null values
Solar_Zenith_Angle                  53732  non-null values
dtypes: datetime64[ns](1), float64(22), object(1)

データフレームの各行に関数を適用することに基づいて、このデータフレームに 2 つの新しい列を作成したいと考えています。applyかなり計算量が多いため、関数を複数回呼び出す必要はありません (たとえば、2 つの別々の呼び出しを行うことによって)。これを 2 つの方法で試しましたが、どちらも機能しません。


使用apply:

Seriesを受け取り、必要な値のタプルを返す関数を作成しました。

def calculate(s):
    a = s['path'] + 2*s['row'] # Simple calc for example
    b = s['path'] * 0.153
    return (a, b)

これを DataFrame に適用しようとすると、エラーが発生します。

st.apply(calculate, axis=1)
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-248-acb7a44054a7> in <module>()
----> 1 st.apply(calculate, axis=1)

C:\Python27\lib\site-packages\pandas\core\frame.pyc in apply(self, func, axis, broadcast, raw, args, **kwds)
   4191                     return self._apply_raw(f, axis)
   4192                 else:
-> 4193                     return self._apply_standard(f, axis)
   4194             else:
   4195                 return self._apply_broadcast(f, axis)

C:\Python27\lib\site-packages\pandas\core\frame.pyc in _apply_standard(self, func, axis, ignore_failures)
   4274                 index = None
   4275 
-> 4276             result = self._constructor(data=results, index=index)
   4277             result.rename(columns=dict(zip(range(len(res_index)), res_index)),
   4278                           inplace=True)

C:\Python27\lib\site-packages\pandas\core\frame.pyc in __init__(self, data, index, columns, dtype, copy)
    390             mgr = self._init_mgr(data, index, columns, dtype=dtype, copy=copy)
    391         elif isinstance(data, dict):
--> 392             mgr = self._init_dict(data, index, columns, dtype=dtype)
    393         elif isinstance(data, ma.MaskedArray):
    394             mask = ma.getmaskarray(data)

C:\Python27\lib\site-packages\pandas\core\frame.pyc in _init_dict(self, data, index, columns, dtype)
    521 
    522         return _arrays_to_mgr(arrays, data_names, index, columns,
--> 523                               dtype=dtype)
    524 
    525     def _init_ndarray(self, values, index, columns, dtype=None,

C:\Python27\lib\site-packages\pandas\core\frame.pyc in _arrays_to_mgr(arrays, arr_names, index, columns, dtype)
   5411 
   5412     # consolidate for now
-> 5413     mgr = BlockManager(blocks, axes)
   5414     return mgr.consolidate()
   5415 

C:\Python27\lib\site-packages\pandas\core\internals.pyc in __init__(self, blocks, axes, do_integrity_check)
    802 
    803         if do_integrity_check:
--> 804             self._verify_integrity()
    805 
    806         self._consolidate_check()

C:\Python27\lib\site-packages\pandas\core\internals.pyc in _verify_integrity(self)
    892                                      "items")
    893             if block.values.shape[1:] != mgr_shape[1:]:
--> 894                 raise AssertionError('Block shape incompatible with manager')
    895         tot_items = sum(len(x.items) for x in self.blocks)
    896         if len(self.items) != tot_items:

AssertionError: Block shape incompatible with manager

次に、この質問applyに示されている方法を使用して、返された値を 2 つの新しい列に割り当てます。しかし、私はここまでたどり着けません!値を 1 つだけ返すと、これはすべて正常に機能します。


ループの使用:

最初にデータフレームの 2 つの新しい列を作成し、次のように設定しましたNone

st['a'] = None
st['b'] = None

次に、すべてのインデックスをループして、そこにあるこれらのNone値を変更しようとしましたが、行った変更は機能していないようでした。つまり、エラーは生成されませんでしたが、DataFrame は変更されていないようです。

for i in st.index:
    # do calc here
    st.ix[i]['a'] = a
    st.ix[i]['b'] = b

これらの方法はどちらもうまくいくと思っていましたが、どちらもうまくいきませんでした。それで、私はここで何が間違っていますか?そして、これを行うための最良の、最も「Pythonic」で「パンダオニック」な方法は何ですか?

4

4 に答える 4

28

最初のアプローチを機能させるには、タプルの代わりに Series を返してみてください (列の数が元のフレームと一致しないため、行を元に戻す方法がわからないため、apply は例外をスローします)。

def calculate(s):
    a = s['path'] + 2*s['row'] # Simple calc for example
    b = s['path'] * 0.153
    return pd.Series(dict(col1=a, col2=b))

以下を置き換えると、2 番目のアプローチが機能するはずです。

st.ix[i]['a'] = a

と:

st.ix[i, 'a'] = a
于 2013-02-28T01:21:16.033 に答える
18

私は常にラムダと組み込みmap()関数を使用して、他の行を組み合わせて新しい行を作成します。

st['a'] = map(lambda path, row: path + 2 * row, st['path'], st['row'])

数値列の線形結合を行うには、必要以上に複雑になる場合があります。一方で、より複雑な行の組み合わせ (文字列の操作など) や、他の列の関数を使用して列の欠落データを埋めるために使用できるため、規則として採用するのは良いことだと思います。

たとえば、性別とタイトルの列を含むテーブルがあり、一部のタイトルが欠落しているとします。次のように関数でそれらを埋めることができます。

title_dict = {'male': 'mr.', 'female': 'ms.'}
table['title'] = map(lambda title,
    gender: title if title != None else title_dict[gender],
    table['title'], table['gender'])
于 2014-06-14T18:14:40.657 に答える
5

これはここで解決されました: Apply pandas function to column to create multiple new columns?

あなたの質問に適用すると、これはうまくいくはずです:

def calculate(s):
    a = s['path'] + 2*s['row'] # Simple calc for example
    b = s['path'] * 0.153
    return pd.Series({'col1': a, 'col2': b})

df = df.merge(df.apply(calculate, axis=1), left_index=True, right_index=True)
于 2013-07-23T13:48:07.547 に答える
0

メソッドチェーンでの新しい列の割り当てに基づくさらに別のソリューション:

st.assign(a = st['path'] + 2*st['row'], b = st['path'] * 0.153)

元の DataFrame はそのままにして、assign 常にデータのコピーを返すことに注意してください。

于 2016-05-10T05:11:29.907 に答える