R言語でデータフレームを1行ずつ計算【1】


データフレームを1行ずつ処理をするときに役立つTipsメモです。
自習用に調べたことなので、入門者レベルかもしれません。ご了承ください。
for文を使い行ごとの処理をできますが、もう少しシンプルに（かつ自分にとってわかりやすい方法で）やりたいと考えました。
別の方法を見つけた場合は追加していきたいと思います。

## rowwise

まず、**tidyverse**に含まれている**dplyr**パッケージで使える**rowwise**。
データに、Rのサンプルとして付いている**「iris」**を使います。

```r
iris
    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
1            5.1         3.5          1.4         0.2     setosa
2            4.9         3.0          1.4         0.2     setosa
3            4.7         3.2          1.3         0.2     setosa
4            4.6         3.1          1.5         0.2     setosa
5            5.0         3.6          1.4         0.2     setosa
6            5.4         3.9          1.7         0.4     setosa
7            4.6         3.4          1.4         0.3     setosa
8            5.0         3.4          1.5         0.2     setosa
9            4.4         2.9          1.4         0.2     setosa
10           4.9         3.1          1.5         0.1     setosa
```

Sepal（がく片）、Petal（花弁）それぞれの平均を行ごとに計算し、mean_Sepal、mean_Pepa列を作成し配置しています。

```r
iris %>%
  as_tibble() %>% #tibble型のデータフレームに変換（なくても集計可）
  rowwise() %>% 
  mutate(
    mean_Sepal = mean(c(Sepal.Length, Sepal.Width)),
    mean_Pepal = mean(c(Petal.Length, Petal.Width))
  )

# A tibble: 150 x 7
# Rowwise: 
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species mean_Sepal mean_Pepal
          <dbl>       <dbl>        <dbl>       <dbl> <fct>        <dbl>      <dbl>
 1          5.1         3.5          1.4         0.2 setosa        4.3        0.8 
 2          4.9         3            1.4         0.2 setosa        3.95       0.8 
 3          4.7         3.2          1.3         0.2 setosa        3.95       0.75
 4          4.6         3.1          1.5         0.2 setosa        3.85       0.85
 5          5           3.6          1.4         0.2 setosa        4.3        0.8 
 6          5.4         3.9          1.7         0.4 setosa        4.65       1.05
 7          4.6         3.4          1.4         0.3 setosa        4          0.85
 8          5           3.4          1.5         0.2 setosa        4.2        0.85
 9          4.4         2.9          1.4         0.2 setosa        3.65       0.8 
10          4.9         3.1          1.5         0.1 setosa        4          0.8 
# ... with 140 more rows
```

## rowwiseコメントアウト

rowwiseがないとどうなるか？、確かめてみます。
rowwiseをコメントアウトすると、

```r
iris %>%
  as_tibble() %>% #tibble型のデータフレームに変換（なくても集計可）
  #rowwise() %>% 
  mutate(
    mean_Sepal = mean(c(Sepal.Length, Sepal.Width)),
    mean_Pepal = mean(c(Petal.Length, Petal.Width))
  )

# A tibble: 150 x 7
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species mean_Sepal mean_Pepal
          <dbl>       <dbl>        <dbl>       <dbl> <fct>        <dbl>      <dbl>
 1          5.1         3.5          1.4         0.2 setosa        4.45       2.48
 2          4.9         3            1.4         0.2 setosa        4.45       2.48
 3          4.7         3.2          1.3         0.2 setosa        4.45       2.48
 4          4.6         3.1          1.5         0.2 setosa        4.45       2.48
 5          5           3.6          1.4         0.2 setosa        4.45       2.48
 6          5.4         3.9          1.7         0.4 setosa        4.45       2.48
 7          4.6         3.4          1.4         0.3 setosa        4.45       2.48
 8          5           3.4          1.5         0.2 setosa        4.45       2.48
 9          4.4         2.9          1.4         0.2 setosa        4.45       2.48
10          4.9         3.1          1.5         0.1 setosa        4.45       2.48
# ... with 140 more rows
```

となります。
行ごとの集計が行われず、mean_Sepal列にはSepal.Length列とSepal.Width列全体の平均値が並びます。
以下の集計と同じ値です。

```r
mean(c(iris$Sepal.Length,iris$Sepal.Width))
[1] 4.450333
```

## rowMeans

上記のように平均を求める場合は、**rowMeans**も使えます。
Rの基本パッケージ（標準R）に含まれる関数です。

```r
iris %>%
  as_tibble() %>% #tibble型のデータフレームに変換（なくても集計可）
  mutate(
    mean_Sepal = rowMeans(iris[,c(1,2)]), #1列目と2列目を指定
    mean_Pepal = rowMeans(iris[,c(3,4)])  #3列目と4列目を指定
  )

# A tibble: 150 x 7
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species mean_Sepal mean_Pepal
          <dbl>       <dbl>        <dbl>       <dbl> <fct>        <dbl>      <dbl>
 1          5.1         3.5          1.4         0.2 setosa        4.3        0.8 
 2          4.9         3            1.4         0.2 setosa        3.95       0.8 
 3          4.7         3.2          1.3         0.2 setosa        3.95       0.75
 4          4.6         3.1          1.5         0.2 setosa        3.85       0.85
 5          5           3.6          1.4         0.2 setosa        4.3        0.8 
 6          5.4         3.9          1.7         0.4 setosa        4.65       1.05
 7          4.6         3.4          1.4         0.3 setosa        4          0.85
 8          5           3.4          1.5         0.2 setosa        4.2        0.85
 9          4.4         2.9          1.4         0.2 setosa        3.65       0.8 
10          4.9         3.1          1.5         0.1 setosa        4          0.8 
# ... with 140 more rows
```

行の和を計算する場合は**rowSums**を使います。

## apply

よく使われる関数**apply**でもできます。
こちらも標準Rに含まれています。

```r
iris %>%
  as_tibble() %>% #tibble型のデータフレームに変換（なくても集計可）
  mutate(
    mean_Sepal = apply(iris[, c("Sepal.Length", "Sepal.Width")], 1, mean),
    mean_Pepal = apply(iris[, c("Petal.Length", "Petal.Width")], 1, mean)
  ) #applyの中の2番目の引数は、1は各行を毎意味する（2は各列を意味する）

# A tibble: 150 x 7
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species mean_Sepal mean_Pepal
          <dbl>       <dbl>        <dbl>       <dbl> <fct>        <dbl>      <dbl>
 1          5.1         3.5          1.4         0.2 setosa        4.3        0.8 
 2          4.9         3            1.4         0.2 setosa        3.95       0.8 
 3          4.7         3.2          1.3         0.2 setosa        3.95       0.75
 4          4.6         3.1          1.5         0.2 setosa        3.85       0.85
 5          5           3.6          1.4         0.2 setosa        4.3        0.8 
 6          5.4         3.9          1.7         0.4 setosa        4.65       1.05
 7          4.6         3.4          1.4         0.3 setosa        4          0.85
 8          5           3.4          1.5         0.2 setosa        4.2        0.85
 9          4.4         2.9          1.4         0.2 setosa        3.65       0.8 
10          4.9         3.1          1.5         0.1 setosa        4          0.8 
# ... with 140 more rows
```

rowMeansで使ったように列番号指定でもできます。

```r
iris %>%
  as_tibble() %>% #tibble型のデータフレームに変換（なくても集計可）
  mutate(
    mean_Sepal = apply(iris[, c(1,2)], 1, mean),
    mean_Pepal = apply(iris[, c(3,4)], 1, mean)
  )

# A tibble: 150 x 7
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species mean_Sepal mean_Pepal
          <dbl>       <dbl>        <dbl>       <dbl> <fct>        <dbl>      <dbl>
 1          5.1         3.5          1.4         0.2 setosa        4.3        0.8 
 2          4.9         3            1.4         0.2 setosa        3.95       0.8 
 3          4.7         3.2          1.3         0.2 setosa        3.95       0.75
 4          4.6         3.1          1.5         0.2 setosa        3.85       0.85
 5          5           3.6          1.4         0.2 setosa        4.3        0.8 
 6          5.4         3.9          1.7         0.4 setosa        4.65       1.05
 7          4.6         3.4          1.4         0.3 setosa        4          0.85
 8          5           3.4          1.5         0.2 setosa        4.2        0.85
 9          4.4         2.9          1.4         0.2 setosa        3.65       0.8 
10          4.9         3.1          1.5         0.1 setosa        4          0.8 
# ... with 140 more rows
```

## map

**map**は、**purrr**パッケージを利用すると使えます。
purrrも、先述のdplyr同様、**tidyverse**に含まれています。
まだ調べ中なので、Sepal（がく片）、Petal（花弁）それぞれ個別に集計しています。
もっと効率よくできそうでです。

手順としては、集計対処の列を**ネスト（nest）**して、リスト型のデータとして格納します。
計算後、ネストを解除（unnnest）してリストを展開することで、列に切り替えています。
**map**関数を使うことで、行単位で指定した計算をしてくれます。
ただし、計算対象はリスト型で、リスト全体をまとめて集計するようなので、「Sepal（がく片）の列だけ取り出してmapで処理」「、Petal（花弁）列だけ取り出してmapで処理」と、今の時点では分けています。

```r
#Sepal（がく片）
iris %>% 
  as_tibble() %>% 
  select(1, 2) %>% 
  rowid_to_column("id") %>% #nest（畳み込み）しやすいように行番号を振る
  group_nest(id) %>% #行番号でnest
  mutate(mean = map(data, ~ mean(unlist(.x)))) %>% #「~」&「.x」が直前に指定した列を指定する
  unnest(cols = c(data, mean)) #nestを解除

# A tibble: 150 x 4
      id Sepal.Length Sepal.Width  mean
   <int>        <dbl>       <dbl> <dbl>
 1     1          5.1         3.5  4.3 
 2     2          4.9         3    3.95
 3     3          4.7         3.2  3.95
 4     4          4.6         3.1  3.85
 5     5          5           3.6  4.3 
 6     6          5.4         3.9  4.65
 7     7          4.6         3.4  4   
 8     8          5           3.4  4.2 
 9     9          4.4         2.9  3.65
10    10          4.9         3.1  4   
# ... with 140 more rows

iris2 <-
  iris %>% 
  as_tibble() %>% 
  select(3, 4) %>% 
  rowid_to_column("id") %>% #nest（畳み込み）しやすいように行番号を振る
  group_nest(id) %>% #行番号でnest
  mutate(mean = map(data, ~ mean(unlist(.x)))) %>% 
  unnest(cols = c(data, mean)) #nestを解除

# A tibble: 150 x 4
      id Petal.Length Petal.Width  mean
   <int>        <dbl>       <dbl> <dbl>
 1     1          1.4         0.2  0.8 
 2     2          1.4         0.2  0.8 
 3     3          1.3         0.2  0.75
 4     4          1.5         0.2  0.85
 5     5          1.4         0.2  0.8 
 6     6          1.7         0.4  1.05
 7     7          1.4         0.3  0.85
 8     8          1.5         0.2  0.85
 9     9          1.4         0.2  0.8 
10    10          1.5         0.1  0.8 
# ... with 140 more rows
```

**了**