Help us understand the problem. What is going on with this article?

{dplyr::filter}のfactor型処理後に、droplevels()でLevelsの要素を整える

More than 1 year has passed since last update.

概要

R言語でのデータ前処理を楽にしてくれる{dplyr}パッケージには、マトリクスデータから指定列の条件に合う行のみを抽出してくれるfilter()という便利な関数があります。

ただfilter()関数は、各列から因子(factor)型の種類を示すlevelsが抽出元のデータのままになる特徴があり、そのままにしておくと、例えば{graphics::plot}で余分な部分を含んでプロットしてしまう。そのためdroplevels()関数を用いて、Levelsの要素を整えてあげる必要があります。

以降にて、データの準備と抽出処理と調整までの、一連の説明とコードを記載します。
(なお{ggplot2}パッケージであれば、調整せずとも簡単にプロットできます)

説明とコード

パッケージとデータの準備

パッケージを読込({tidyverse}のみでも可)

library(dplyr) #0.7.1
library(data.table) #1.10.4

「商品3種(apple,banana,orange)を担当者4人(A,B,C,D)が何個売ったか」のサンプルデータを生成

set.seed(11)
product <- sample(factor(c("apple","banana","orange")),size=30,replace=TRUE)
number <- sample(c(1:10),size = 30,replace = TRUE)
staff <- sample(factor(c("A","B","C","D")),size= 30,replace= TRUE)

sales_dt <- data.table(PRODUCT = product,NUMBER = number,STAFF = staff)
head(sales_dt)
PRODUCT NUMBER STAFF
1 apple 6 A
2 apple 4 D
3 banana 5 A
4 apple 3 C
5 apple 9 D
6 orange 7 A

filter()関数で、「担当者AもしくはDの、appleの販売個数」と条件づけてデータを抽出。

sales_dt %>% 
  filter(STAFF == "A" | STAFF =="D") %>%
  filter(PRODUCT == "apple") -> filter_sales_dt

抽出前後データの因子を確認

抽出元のsales_dtの因子要素を確認する。

sapply(sales_dt, FUN = "levels")
$PRODUCT
[1] "apple"  "banana" "orange"

$NUMBER
NULL

$STAFF
[1] "A" "B" "C" "D"

抽出後のfilter_sales_dtの因子要素を確認する。

sapply(filter_sales_dt, FUN = "levels")
$PRODUCT
[1] "apple"  "banana" "orange"

$NUMBER
NULL

$STAFF
[1] "A" "B" "C" "D"

どちらも同じ結果が表示されていることがわかる。
(変数$NUMBERは整数(integer)型のためNULL表記)

droplevels()を用いてlevels要素を整える

droplevels()を用いて、不要な因子型を取り除く。

check_dt <- droplevels(filter_sales_dt)
sapply(check_dt, FUN = "levels")
$PRODUCT
[1] "apple"

$NUMBER
NULL

$STAFF
[1] "A" "D"

なお、もしこの調整をしないでプロットすると、不要な担当者"B"と"C"まで含めてしまう。

plot(filter_sales_dt$STAFF, filter_sales_dt$NUMBER)

Rplot.png

最後に

今後もしこのようにプロットされる事に遭遇したら、まずLevelsを疑うことがオススメです。
{ggplot2}以外でプロットしなければいけない場合(決定木で{rpart.plot}を使う場合など)は、データ型の取り扱いミスしていないか確認すると近道かも。

参照元

Rで解析:不要な水準を取り除く「droplevels」コマンド
https://www.karada-good.net/analyticsr/r-319

How to drop unused levels after filtering by factor? [duplicate]
https://stackoverflow.com/questions/26826865/how-to-drop-unused-levels-after-filtering-by-factor

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away