12. 使用布尔值、整数、标签进行选取

  1. # 读取movie,根据布尔条件选取
  2. In[89]: movie = pd.read_csv('data/movie.csv', index_col='movie_title')
  3. c1 = movie['content_rating'] == 'G'
  4. c2 = movie['imdb_score'] < 4
  5. criteria = c1 & c2
  6. In[90]: movie_loc = movie.loc[criteria]
  7. movie_loc.head()
  8. Out[90]:

12. 使用布尔值、整数、标签进行选取 - 图1

  1. # 检查loc条件和布尔条件创建出来的两个DataFrame是否一样
  2. In[91]: movie_loc.equals(movie[criteria])
  3. Out[91]: True
  1. # 尝试用.iloc使用布尔索引
  2. In[92]: movie_iloc = movie.iloc[criteria]
  3. ---------------------------------------------------------------------------
  4. ValueError Traceback (most recent call last)
  5. <ipython-input-92-24a12062c6c3> in <module>()
  6. ----> 1 movie_iloc = movie.iloc[criteria]
  7. /Users/Ted/anaconda/lib/python3.6/site-packages/pandas/core/indexing.py in __getitem__(self, key)
  8. 1326 else:
  9. 1327 key = com._apply_if_callable(key, self.obj)
  10. -> 1328 return self._getitem_axis(key, axis=0)
  11. 1329
  12. 1330 def _is_scalar_access(self, key):
  13. /Users/Ted/anaconda/lib/python3.6/site-packages/pandas/core/indexing.py in _getitem_axis(self, key, axis)
  14. 1731
  15. 1732 if is_bool_indexer(key):
  16. -> 1733 self._has_valid_type(key, axis)
  17. 1734 return self._getbool_axis(key, axis=axis)
  18. 1735
  19. /Users/Ted/anaconda/lib/python3.6/site-packages/pandas/core/indexing.py in _has_valid_type(self, key, axis)
  20. 1588 "indexing on an integer type "
  21. 1589 "is not available")
  22. -> 1590 raise ValueError("iLocation based boolean indexing cannot use "
  23. 1591 "an indexable as a mask")
  24. 1592 return True
  25. ValueError: iLocation based boolean indexing cannot use an indexable as a mask
  1. # 但是,却可以使用布尔值得ndarray,用values可以取出array
  2. In[93]: movie_iloc = movie.iloc[criteria.values]
  3. In[94]: movie_iloc.equals(movie_loc)
  4. Out[94]: True
  5. In[95]: movie.loc[criteria.values]
  6. Out[95]:

12. 使用布尔值、整数、标签进行选取 - 图2

  1. # 布尔索引也可以用来选取列
  2. In[96]: criteria_col = movie.dtypes == np.int64
  3. criteria_col.head()
  4. Out[96]: color False
  5. director_name False
  6. num_critic_for_reviews False
  7. duration False
  8. director_facebook_likes False
  9. dtype: bool
  1. In[97]: movie.loc[:, criteria_col].head()
  2. Out[97]:

12. 使用布尔值、整数、标签进行选取 - 图3

  1. # 因为criteria_col是包含行索引的一个Series,必须要使用底层的ndarray,才能使用,iloc
  2. In[98]: movie.iloc[:, criteria_col.values].head()
  3. Out[98]:

12. 使用布尔值、整数、标签进行选取 - 图4

  1. # 选取'content_rating', 'imdb_score', 'title_year', 'gross'四列,按照imdb_score升序排列
  2. In[99]: cols = ['content_rating', 'imdb_score', 'title_year', 'gross']
  3. movie.loc[criteria, cols].sort_values('imdb_score')
  4. Out[99]:

12. 使用布尔值、整数、标签进行选取 - 图5

  1. # 用get_loc获取这四列的整数位置
  2. In[100]: col_index = [movie.columns.get_loc(col) for col in cols]
  3. col_index
  4. Out[100]: [20, 24, 22, 8]
  1. # 这时候就可以使用iloc了
  2. In[101]: movie.iloc[criteria.values, col_index].sort_values('imdb_score')
  3. Out[101]:

12. 使用布尔值、整数、标签进行选取 - 图6

原理

  1. # 查看Series的底层结构
  2. In[102]: a = criteria.values
  3. a[:5]
  4. Out[102]: array([False, False, False, False, False], dtype=bool)
  5. In[103]: len(a), len(criteria)
  6. Out[103]: (4916, 4916)

更多

  1. # 传入的布尔索引可以跟要操作的DataFrame长度不同
  2. In[104]: movie.loc[[True, False, True], [True, False, False, True]]
  3. Out[104]:

12. 使用布尔值、整数、标签进行选取 - 图7