Tôi có một DataFrame gấu trúc, st
chứa nhiều cột:Áp dụng chức năng để mỗi hàng của gấu trúc dataframe để tạo ra hai cột mới
<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)
Tôi muốn tạo ra hai cột mới cho dataframe này dựa trên việc áp dụng một chức năng để mỗi hàng của khung dữ liệu. Tôi không muốn phải gọi hàm này nhiều lần (ví dụ: bằng cách thực hiện hai cuộc gọi riêng biệt apply
) vì nó khá tốn kém tính toán. Tôi đã cố gắng làm điều này theo hai cách, và không ai trong số họ làm việc:
Sử dụng apply
:
Tôi đã viết một chức năng mà phải mất một Series
và trả về một tuple trong những giá trị tôi muốn:
def calculate(s):
a = s['path'] + 2*s['row'] # Simple calc for example
b = s['path'] * 0.153
return (a, b)
Đang cố gắng để áp dụng điều này để các DataFrame đưa ra một lỗi:
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
Sau đó, tôi sẽ chỉ định các giá trị được trả lại từ apply
thành hai cột mới bằng cách sử dụng phương thức được hiển thị trong this question. Tuy nhiên, tôi thậm chí không thể đến được điểm này! Tất cả điều này hoạt động tốt nếu tôi chỉ trả lại một giá trị.
Sử dụng một vòng lặp:
đầu tiên tôi tạo ra hai cột mới của dataframe và đặt chúng vào None
:
st['a'] = None
st['b'] = None
Sau đó looped qua tất cả các chỉ số và cố gắng sửa đổi những giá trị None
mà tôi có trong đó, nhưng những sửa đổi tôi đã làm dường như không hoạt động. Tức là, không có lỗi nào được tạo ra, nhưng DataFrame dường như không bị sửa đổi.
for i in st.index:
# do calc here
st.ix[i]['a'] = a
st.ix[i]['b'] = b
Tôi nghĩ rằng cả hai phương pháp sẽ làm việc, nhưng không ai trong số họ đã làm. Vì vậy, tôi đang làm gì sai ở đây? Và cách tốt nhất, 'pythonic' và 'pandaonic' tốt nhất để làm điều này là gì?
Giải pháp cho phương pháp tiếp cận thứ hai hoạt động - cảm ơn :-). Tuy nhiên, tôi không thể có được cách tiếp cận đầu tiên để làm việc. Trả về một chuỗi các công trình, và tôi nhận được một 'mini-df' trả về, nhưng tôi dường như không thể lấy lại các giá trị từ hàm 'apply' vào khung dữ liệu ban đầu. Sử dụng 'st ['a'], st ['b'] = st.apply (tính, trục = 1)' không hoạt động, và không bao bọc phần bên phải trong 'zip (*)'. Bất kỳ ý tưởng về những gì tôi đang làm sai ở đây? – robintw
Bạn có thể nối các cột 'mini' df vào DataFrame gốc với 'pd.concat ([df, new_df], axis = 1)'. Bạn cũng có thể muốn xem xét các hoạt động dựa trên cột, thay vì dựa trên hàng, ví dụ, tính toán và thêm cột 'a' với 'df ['a'] = df ['path'] + 2 * df ['row'] ' – Garrett