LoginSignup
0
0

セルの値を複数行・複数列に展開する

Last updated at Posted at 2024-02-06

はじめに

セルの値を区切り文字で分離して複数行に展開するtidyr::separate_longer_delim()関数や複数列に展開するtidyr::separate_wider_delim()関数を使う機会があったので,忘れないうちにメモしておきます.

データ

東京電力ホールディングスのWebサイトに数表で見る東京電力というページがあり,そこでは東京電力に関わる色々なデータをダウンロードすることができます.
今回は平均モデルの電気料金のデータをダウンロードし,このページにあるグラフを再現したいと思います.

早速データをダウンロードします.

2024-02-06.png

ダウンロードした6241_change-001.csvを適当なディレクトリに移動し,RStudioでインポートしてみます.

2024-02-06 (1).png

2行スキップすれば読み込めそうです.縦横は後で入れ替えることにします.

2024-02-06 (3).png

ということでdf_chargeというデータフレームに読み込むことにします.

library(tidyverse)

X6241_charge_001 <- read_csv("6241_charge-001.csv", skip = 2)
df_charge <- as_tibble(
  cbind(
    適用期間 = names(X6241_charge_001)[-1],
    電気料金 = t(X6241_charge_001)[-1]
    )
  ) |>
  mutate(電気料金 = as.numeric(電気料金))

できあがったデータフレームは四半期毎のデータのようです.

2024-02-06 (4).png

ん?

2024-02-06 (5).png

んんん?

2024-02-06 (6).png

どうも四半期毎になっているのは2009年の第1四半期までで,それ以降は月次のデータとなっているようです1.そこで,このデータフレーム全体を月次データとして変換することにします.そのために,四半期毎になっている行については,電気料金の値を3ヶ月分複製した行を挿入します.

処理

つまり,

適用期間 電気料金
2009/1~3 7206

という行を

適用期間 電気料金
2009/01 7206
2009/02 7206
2009/03 7206

という3行に変換したいわけです.

下準備として適用期間の値を年と月を表す列に/で分割するために,separate_wider_delim()関数を使います.

df_charge <- df_charge |>
  separate_wider_delim(
    適用期間,
    delim = "/",
    names = c("年", "月"),
    too_few = "align_start"
    )

df_charge
# A tibble: 189 × 3
            電気料金
   <chr> <chr>     <dbl>
 1 2004  46       6418
 2 2004  79       6418
 3 2004  1012     6142
 4 2005  13       6200
 5 2005  46       6224
 6 2005  79       6203
 7 2005  1012     6294
 8 2006  13       6429
 9 2006  46       6269
10 2006  79       6269
# ℹ 179 more rows
# ℹ Use `print(n = ...)` to see more rows

too_few = "align_start"は2つに分割できない場合(Sep-22のケース)に先頭から値を埋めて,残りにNAを入れることを指定しています.

df_charge |>
  filter( == "Sep-22")
# A tibble: 1 × 3
           電気料金
  <chr>  <chr>    <dbl>
1 Sep-22 NA        6797

次に7~9などの四半期のラベルを,カンマ区切りの数字(7,8,9など)で置換し,2008年9月の値も処理します.

df_charge <- df_charge |>
  mutate(
     = if_else(is.na(), "9", ),    
     = case_when(
       == "1~3" ~ "1,2,3",
       == "4~6" ~ "4,5,6",
       == "7~9" ~ "7,8,9",
       == "10~12" ~ "10,11,12",
       == "7~8" ~ "7,8",
      TRUE ~ 
      ),
     = if_else( == "Sep-22", "2008", )
    )

この列に対してseparate_longer_delim()関数を使います.

df_charge <- df_charge |>
  separate_longer_delim(, delim = ",")

df_charge
# A tibble: 228 × 3
           電気料金
   <chr> <chr>    <dbl>
 1 2004  4         6418
 2 2004  5         6418
 3 2004  6         6418
 4 2004  7         6418
 5 2004  8         6418
 6 2004  9         6418
 7 2004  10        6142
 8 2004  11        6142
 9 2004  12        6142
10 2005  1         6200
# ℹ 218 more rows
# ℹ Use `print(n = ...)` to see more rows

データフレーム全体の行数も189行から228行に増えていることが分かります.

最後に折れ線グラフを描いて完成です.

library(tsibble)

df_charge |>
  mutate(年月 = make_yearmonth(year = , month = )) |>
  select(年月, 電気料金) |>
  as_tsibble(index = 年月) |>
  ggplot(aes(x = 年月, y = 電気料金)) +
  geom_point() + geom_line()

Rplot.png

終わりに

今回のケースであれば欠落データはなさそうですので,tidyr::uncount()関数を使って行をコピーしてから,別途作成したインデックスと組み合わせても実現できると思います.

それにしてもどうやったらこんなヘンテコなデータができるんでしょうかね?

  1. よく見ると上の東京電力ホールディングスのページにあるグラフも横軸が等間隔にはなってないですね.

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0