2015-10-19 14 views
6

Tôi có mã sau và nó hoạt động. Điều này về cơ bản đổi tên các giá trị trong cột để chúng có thể được sáp nhập sau này.Cảnh báo Pandas khi sử dụng bản đồ: Giá trị đang cố gắng được đặt trên bản sao của một lát từ Khung dữ liệu

pop = pd.read_csv('population.csv') 
pop_recent = pop[pop['Year'] == 2014] 

mapping = { 
     'Korea, Rep.': 'South Korea', 
     'Taiwan, China': 'Taiwan' 
} 
f= lambda x: mapping.get(x, x) 
pop_recent['Country Name'] = pop_recent['Country Name'].map(f) 

Cảnh báo: Một giá trị đang cố gắng để được đặt trên một bản sao của một lát từ một DataFrame. Hãy thử sử dụng .loc [row_indexer, col_indexer] = giá trị thay vì Xem những hãy cẩn thận trong tài liệu:. http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy pop_recent [ 'Tên Nước'] = pop_recent [ 'Nước Tên'] bản đồ (f)

Tôi đã làm điều này! Nhưng không có ví dụ nào có vẻ là sử dụng bản đồ, vì vậy tôi đang thua lỗ ...

+0

Làm sao bạn có được pop_recent? –

+0

Đã thêm một số mã ... – Mike

+0

Hãy thử những gì cảnh báo đang nói đến - pop.loc [(pop ['năm'] == 2014), 'Tên quốc gia'] = pop.loc [(pop ['year'] = = 2014), 'Tên quốc gia'] Bản đồ (f) –

Trả lời

10

Vấn đề là với chained indexing, những gì bạn đang thực sự cố gắng làm là để thiết lập giá trị cho - pop[pop['Year'] == 2014]['Country Name'] - điều này sẽ không làm việc hầu hết các lần (như giải thích rất tốt trong tài liệu liên kết) vì đây là hai cuộc gọi khác nhau và một trong các cuộc gọi có thể trả lại bản sao của khung dữ liệu (tôi tin rằng lập chỉ mục boolean) đang trả về bản sao của khung dữ liệu).

Do đó, khi bạn cố đặt giá trị cho bản sao đó, nó không phản ánh trong khung dữ liệu gốc. Ví dụ -

In [6]: df 
Out[6]: 
    A B 
0 1 2 
1 3 4 
2 4 5 
3 6 7 
4 8 9 

In [7]: df[df['A']==1]['B'] = 10 
/path/to/ipython-script.py:1: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame. 
Try using .loc[row_indexer,col_indexer] = value instead 

See the the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy 
    if __name__ == '__main__': 

In [8]: df 
Out[8]: 
    A B 
0 1 2 
1 3 4 
2 4 5 
3 6 7 
4 8 9 

Như đã đề cập, thay vì chỉ mục xích bạn nên sử dụng DataFrame.loc chỉ mục các hàng cũng như các cột để cập nhật trong một cuộc gọi duy nhất, tránh được lỗi này. Ví dụ -

pop.loc[(pop['year'] == 2014), 'Country Name'] = pop.loc[(pop['year'] == 2014), 'Country Name'].map(f) 

Hoặc nếu điều này có vẻ quá dài đối với bạn, bạn có thể tạo mặt nạ (boolean dataframe) trước và gán cho một biến và sử dụng trong tuyên bố ở trên. Ví dụ -

mask = pop['year'] == 2014 
pop.loc[mask,'Country Name'] = pop.loc[mask,'Country Name'].map(f) 

Demo -

In [9]: df 
Out[9]: 
    A B 
0 1 2 
1 3 4 
2 4 5 
3 6 7 
4 8 9 

In [10]: mapping = { 1:2 , 3:4} 

In [11]: f= lambda x: mapping.get(x, x) 

In [12]: df.loc[(df['B']==2),'A'] = df.loc[(df['B']==2),'A'].map(f) 

In [13]: df 
Out[13]: 
    A B 
0 2 2 
1 3 4 
2 4 5 
3 6 7 
4 8 9 

Demo với mặt nạ phương pháp -

In [18]: df 
Out[18]: 
    A B 
0 1 2 
1 3 4 
2 4 5 
3 6 7 
4 8 9 

In [19]: mask = df['B']==2 

In [20]: df.loc[mask,'A'] = df.loc[mask,'A'].map(f) 

In [21]: df 
Out[21]: 
    A B 
0 2 2 
1 3 4 
2 4 5 
3 6 7 
4 8 9 
+0

Aha ... Vì vậy, nếu tôi lần đầu tiên bản đồ, sau đó lát (vì vậy cách khác vòng), nó hoạt động mà không bitching! – Mike

+0

Có, điều đó cũng hoạt động. –

+3

Tôi ghét gấu trúc. Ấn tượng tôi có là nó là một trong những hack khác không có tính thống nhất. Là một người dùng có kinh nghiệm hơn, bạn nghĩ sao? – Mike

0

Tôi khuyên bạn nên để đặt lại chỉ số trong pop_recent = pop[pop['Year'] == 2014].

Nếu bạn muốn áp dụng một số chức năng cho một số cột của khung dữ liệu, hãy thử sử dụng chức năng apply chức năng của API DataFrame. bản demo đơn giản:

mapping = { 
     'Korea, Rep.': 'South Korea', 
     'Taiwan, China': 'Taiwan' 
} 
df = pandas.DataFrame({'Country':['Korea, Rep.', 'Taiwan, China', 'Japan', 'USA'], 'date':[2014, 2014, 2015, 2014]}) 
df_recent = df[df['date'] == 2014].reset_index() 
df_recent['Country'] = df_recent['Country'].apply(lambda x: mapping.get(x, x)) 

Output:

>>> df_recent 
index  Country date 
0  0 South Korea 2014 
1  1  Taiwan 2014 
2  3   USA 2014 
+0

Không, xin lỗi. Nó vẫn còn phàn nàn: Một giá trị đang cố gắng được đặt trên một bản sao của một slice từ một DataFrame. Thử sử dụng .loc [row_indexer, col_indexer] = value thay vì – Mike

+0

Kiểm tra thay đổi của tôi. Nó hoạt dộng bây giờ. – Gregg

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