2015-05-27 12 views
7

Tôi nghĩ tôi đã hiểu bản đồ so với bản đồ áp dụng khá tốt, nhưng đang gặp sự cố (xem here để biết thêm nền, nếu quan tâm).Bản đồ so với bản đồ áp dụng khi chuyển từ điển

Một ví dụ đơn giản:

df = pd.DataFrame([[1,2],[1,1]]) 
dct = { 1:'python', 2:'gator' } 

df[0].map(lambda x: x+90) 
df.applymap(lambda x: x+90) 

đó làm việc như mong đợi - cả hai hoạt động trên cơ sở elementwise, bản đồ trên một loạt, applymap trên dataframe (giải thích rất tốt here btw).

Nếu tôi sử dụng một cuốn từ điển chứ không phải là một lambda, bản đồ vẫn hoạt động tốt:

df[0].map(dct) 

0 python 
1 python 

nhưng không applymap:

df.applymap(dct) 
--------------------------------------------------------------------------- 
TypeError         Traceback (most recent call last) 
<ipython-input-100-7872ff604851> in <module>() 
----> 1 df.applymap(dct) 

C:\Users\johne\AppData\Local\Continuum\Anaconda\lib\site-packages\pandas\core\frame.pyc in applymap(self, func) 
    3856     x = lib.map_infer(_values_from_object(x), f) 
    3857    return lib.map_infer(_values_from_object(x), func) 
-> 3858   return self.apply(infer) 
    3859 
    3860  #---------------------------------------------------------------------- 

C:\Users\johne\AppData\Local\Continuum\Anaconda\lib\site-packages\pandas\core\frame.pyc in apply(self, func, axis, broadcast, raw, reduce, args, **kwds) 
    3687      if reduce is None: 
    3688       reduce = True 
-> 3689      return self._apply_standard(f, axis, reduce=reduce) 
    3690    else: 
    3691     return self._apply_broadcast(f, axis) 

C:\Users\johne\AppData\Local\Continuum\Anaconda\lib\site-packages\pandas\core\frame.pyc in _apply_standard(self, func, axis, ignore_failures, reduce) 
    3777    try: 
    3778     for i, v in enumerate(series_gen): 
-> 3779      results[i] = func(v) 
    3780      keys.append(v.name) 
    3781    except Exception as e: 

C:\Users\johne\AppData\Local\Continuum\Anaconda\lib\site-packages\pandas\core\frame.pyc in infer(x) 
    3855     f = com.i8_boxer(x) 
    3856     x = lib.map_infer(_values_from_object(x), f) 
-> 3857    return lib.map_infer(_values_from_object(x), func) 
    3858   return self.apply(infer) 
    3859 

C:\Users\johne\AppData\Local\Continuum\Anaconda\lib\site-packages\pandas\lib.pyd in pandas.lib.map_infer (pandas\lib.c:56990)() 

TypeError: ("'dict' object is not callable", u'occurred at index 0') 

Vì vậy, câu hỏi của tôi là tại sao không lập bản đồ và làm việc applymap một cách tương tự ở đây? Nó là một lỗi với applicmap, hoặc tôi đang làm điều gì đó sai?

Chỉnh sửa để thêm: Tôi đã phát hiện ra rằng tôi có thể làm việc xung quanh này khá dễ dàng với điều này:

df.applymap(lambda x: dct[x]) 

     0  1 
0 python gator 
1 python python 

Hoặc tốt hơn qua answer này mà không yêu cầu phải lambda.

df.applymap(dct.get) 

Vì vậy, đó là khá chính xác tương đương, phải không? Phải là một cái gì đó với cách áp dụng phân tích cú pháp cú pháp và tôi đoán hình thức rõ ràng của một hàm/phương thức hoạt động tốt hơn một từ điển. Dù sao, tôi đoán bây giờ không có vấn đề thực tế còn lại ở đây nhưng tôi vẫn quan tâm đến những gì đang xảy ra ở đây nếu có ai muốn trả lời.

+1

df.applymap() không áp dụng .map() trên mỗi Series của DataFrame, đặt bản đồ .apply() trên mỗi Series. Xem Chuỗi .apply() tại đây: [link] (http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.apply.html) Và .apply() cần một hàm làm đối số và không thể lấy một từ điển như .map() có thể làm. –

+1

Xin lỗi, tôi thực sự không hiểu bạn đang nói gì ở đây. Tôi đoán rằng áp dụng bản đồ và bản đồ là không tương đương, mà tôi không tranh chấp, nhưng tôi không có bất kỳ sự hiểu biết tốt hơn về lý do tại sao hoặc như thế nào. Để trích dẫn từ liên kết ở trên (đến một câu trả lời SO rất phổ biến): "applymap hoạt động trên phần tử DataFrame và bản đồ hoạt động trên phần tử". Tôi hy vọng cho một số xây dựng vào thời điểm đó. – JohnE

Trả lời

5

.applymap() và .map() là đúng để làm việc theo nguyên tố. Nhưng .applymap() không lấy từng cột và làm .map() trên các cột đó, nhưng làm .apply() trên mỗi cột.

Vì vậy, khi bạn gọi df.applymap (DCT): happend gì là df [0] .apply (DCT), không DF [0] .map (DCT)

Và đây là những gì Sự khác biệt giữa hai phương pháp loạt tài liệu này:

.map() chấp nhận series, dict và chức năng (bất kỳ callable, vì vậy phương pháp như dict.get công việc quá) như là đối số đầu tiên; như .apply() chỉ chấp nhận hàm (hoặc bất kỳ cuộc gọi nào) làm đối số đầu tiên.

.map() chứa câu lệnh if để tìm ra xem đối số đầu tiên có phải là dict hay không, một Series hoặc một hàm và hành động proprely tùy thuộc vào đầu vào. Khi bạn chuyển một hàm tới .map(), phương thức .map() làm những việc giống như .apply().

Nhưng .apply() không có các câu lệnh đó nếu cho phép nó xử lý một cách đáng kinh ngạc với dictionnary và Series. Nó chỉ biết làm thế nào để làm việc với callable.

Khi bạn gọi .apply() hoặc .map() với hàm mà cả hai đều gọi hàm lib.map_infer(), trông giống như hàm map() của python (nhưng Im bật để đặt tay lên mã nguồn nên Im không hoàn toàn chắc chắn).

Thực hiện ánh xạ (dct, df [0]) sẽ cho bạn lỗi giống như df.applymap (dct) và df [0] .apply (dct) cũng sẽ gây ra lỗi tương tự.

Bây giờ, bạn có thể hỏi tại sao sử dụng .apply() thay vì .map(), nếu .map() làm điều tương tự khi được gọi với hàm và có thể lấy dict và Series không?

Vì .apply() có thể trả lại cho bạn một khung dữ liệu nếu kết quả của hàm bạn chuyển đến nó là một chuỗi.

ser = pandas.Series([1,2,3,4,5], index=range(5)) 

ser_map = ser.map(lambda x : pandas.Series([x]*5, index=range(5))) 
type(ser_map) 
pandas.core.series.Series 

ser_app = ser.apply(lambda x : pandas.Series([x]*5, index=range(5))) 
type(ser_app) 
pandas.core.frame.DataFrame 
+0

Xin cảm ơn! Ví dụ cho thấy cách bản đồ tạo ra một chuỗi và áp dụng tạo ra một khung dữ liệu cũng giải thích một số kết quả tôi đã nhận được trong quá khứ và không được hiểu. Sự hiểu biết của tôi về tất cả điều này vẫn còn một chút ít hơn 100%, nhưng điều này sẽ giúp. – JohnE

Các vấn đề liên quan