質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
R

R言語は、「S言語」をオープンソースとして実装なおした、統計解析向けのプログラミング言語です。 計算がとても速くグラフィックも充実しているため、数値計算に向いています。 文法的には、統計解析部分はS言語を参考にしており、データ処理部分はSchemeの影響を受けています。 世界中の専門家が開発に関わり、日々新しい手法やアルゴリズムが追加されています。

Q&A

解決済

1回答

313閲覧

<R>10個体で同一個体ごと5回繰り返し測定した1~5の整数データを個体ごとに測定データの出現回数をカウントしたい!

3535_Toucyan

総合スコア1

R

R言語は、「S言語」をオープンソースとして実装なおした、統計解析向けのプログラミング言語です。 計算がとても速くグラフィックも充実しているため、数値計算に向いています。 文法的には、統計解析部分はS言語を参考にしており、データ処理部分はSchemeの影響を受けています。 世界中の専門家が開発に関わり、日々新しい手法やアルゴリズムが追加されています。

1グッド

0クリップ

投稿2024/07/13 08:56

編集2024/07/13 09:53

---はじめて質問いたします。どうぞよろしくお願いいたします。
R(Rstudio)において、データフレームの集計に難渋しております。

データハンドリングを普段からされていらっしゃる方からすれば、こんな初歩的なことを?と思われるかもしれませんが、上手くたどり着けず時間ばかり消費しており、困っております。
お知恵をお借りできましたら幸いです。

前提

  • 10個の個体において、同一個体ごと5回繰り返し測定した1~5の整数データがある
  • すべてに5回繰り返し測定されていないので、欠損(NA)もある。
  • 時系列データなので、3回目以降がNAという場合や、すべてNAという場合もある。

実現したいこと

  • 各個体ごとに測定データの出現回数をカウントしたい。

手持ちのデータ

データの例としては以下の表のようなデータフレームです
表1

No1回目2回目3回目4回目5回目
11NANANANA
212NANANA
33NANANANA
413NANANA
543431
6111NANA
7413NANA
8NANANANANA
9441NANA
1033NANANA

上記データフレームの作成コードを追加いたします。
dfをお使いいただけますと幸いです。

R

1# 解析用データフレームの作成 df をお使いください。 2No <- c(1:10) 3keisoku1 <- c(1,1,3,1,4,1,4,NA,4,3) 4keisoku2 <- c(NA,2,NA,3,3,1,1,NA,4,3) 5keisoku3 <- c(NA,NA,NA,NA,4,1,3,NA,1,NA) 6keisoku4 <- c(NA,NA,NA,NA,3,NA,NA,NA,NA,NA) 7keisoku5 <- c(NA,NA,NA,NA,1,NA,NA,NA,NA,NA) 8df <- data.frame( 9 No, 10 "1回目" = keisoku1, 11 "2回目" = keisoku2, 12 "3回目" = keisoku3, 13 "4回目" = keisoku4, 14 "5回目" = keisoku5 15 ) 16rm(No,keisoku1,keisoku2,keisoku3,keisoku4,keisoku5) 17

実現したいこと

上記の表1の右側に下記表2のように出現整数をカウントしたデータが追加される
表2

No1回目2回目3回目4回目5回目12345
11NANANANA10000
212NANANA11000
33NANANANA00100
413NANANA10100
54343110220
6111NANA30000
7413NANA10110
8NANANANANA00000
9441NANA10020
1033NANANA00200

試したこと

何分自己流でdplyrやtidyrなどを使ってもうまくいきません。
wide型をlong型に変えるところまではしましたが、
思うような結果につながりません。

補足

個人的な研究、解析です。学校、講習等の課題ではありません。

あまり関係ないかと思いますが、
Rのバージョンは4.4.0
Rstudioのバージョンは 2024.04.2+764 です。

どうぞよろしくお願いいたします。

melian👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

各個体ごとに測定データの出現回数をカウントしたい

データフレームの行ごとに(apply(..., 1, ...))測定データ(seq(1, 5))の出現回数を集計します(sapply(seq(1, 5), ...))。

r

1df <- data.frame( 2 No = 1:10, 3 `1回目` = c(1, 1, 3, 1, 4, 1, 4, NA, 4, 3), 4 `2回目` = c(NA, 2, NA, 3, 3, 1, 1, NA, 4, 3), 5 `3回目` = c(NA, NA, NA, NA, 4, 1, 3, NA, 1, NA), 6 `4回目` = c(NA, NA, NA, NA, 3, NA, NA, NA, NA, NA), 7 `5回目` = c(NA, NA, NA, NA, 1, NA, NA, NA, NA, NA), 8 check.names = FALSE 9) 10 11# 12df <- cbind(df, t(apply(df[,2:6], 1, \(x) sapply(1:5, \(a, b) sum(a==b, na.rm=T), x)))) 13df 14 15# No 1回目 2回目 3回目 4回目 5回目 1 2 3 4 5 16# 1 1 1 NA NA NA NA 1 0 0 0 0 17# 2 2 1 2 NA NA NA 1 1 0 0 0 18# 3 3 3 NA NA NA NA 0 0 1 0 0 19# 4 4 1 3 NA NA NA 1 0 1 0 0 20# 5 5 4 3 4 3 1 1 0 2 2 0 21# 6 6 1 1 1 NA NA 3 0 0 0 0 22# 7 7 4 1 3 NA NA 1 0 1 1 0 23# 8 8 NA NA NA NA NA 0 0 0 0 0 24# 9 9 4 4 1 NA NA 1 0 0 2 0 25# 10 10 3 3 NA NA NA 0 0 2 0 0

追記

①cbindの第二引数、apply前の「t」です。
tは各1〜5の作成された列が入る変数を表している?

t は transpose(転置)関数です。例えば以下では 2x3 行列を 3x2 行列に変換しています。

> a <- matrix(1:6, 2, 3) > a [,1] [,2] [,3] [1,] 1 3 5 [2,] 2 4 6 > t(a) [,1] [,2] [1,] 1 2 [2,] 3 4 [3,] 5 6

なぜこの様なことをしているかと言うと、apply(..., 1, ...) で返るデータフレームが5行10列になっているので、転置して10行5列のデータフレームにしないと元のデータフレーム(df: 10行6列)と結合できないからです。

②「t(apply(df[,2:6],~」」の「df[,2~」でなぜ「,」が必要か?
すでにdfでデータフレームを指定しているので、何の引数を省略しているのでしょうか。

df[,2:6] という表記は「dfの(全ての行の)2列目から6列目」を指しています。df[行範囲, 列範囲] という表記で取り出す部分を指定することができますが、範囲を省略すると全ての行、もしくは全ての列として処理されます。例えば df[1:5,] は「dfの1行目から5行目(までの全ての列)」を指します。また、行や列の指定にはラベルを指定することもできます。例えば df[,c("2回目", "3回目", "4回目")] は「dfの"2回目"列, "3回目"列, "4回目"列」を取り出します。

③バックスラッシュで整数を文字列下していることは分かりました。
「~ (x) sapply(1:5, \~」のsapplyの前にある「(x)」ですが、
変数列名をつくるための変数?これにより各行の変数を示している?

バックスラッシュですが、これは R 4.1.0 から追加された表記方法で、無名関数(anonymous function)を表しています。なので、(x)(a, b) は関数パラメータになります。

# R 4.1.0 以降(function(...) ~ 表記でも可) df <- cbind(df, t(apply(df[,2:6], 1, \(x) sapply(1:5, \(a, b) sum(a==b, na.rm=T), x)))) # R 4.1.0 よりも前のバージョン df <- cbind(df, t(apply(df[,2:6], 1, function(x) sapply(1:5, function(a, b) sum(a==b, na.rm=T), x))))

④「~(a, b) sum(a==b,~」でなぜ、1~5がにaとbに代入されていくのか?
このように前に変数を置く構文がはじめてです。もう少し探してみます。

⑤「~sum(a==b, na.rm=T), x)~」のxは何をしているのか?
この構文のxに意味することがわかりません。

具体的に、5行目のデータでの処理を見てみます。

# 5行目(No == 5)の1回目から5回目の測定データ c(4, 3, 4, 3, 1) # \(x) の x に c(4, 3, 4, 3, 1) が渡されます apply(..., 1, \(c(4, 3, 4, 3, 1)) sapply(1:5, \(a, b) sum(a==b, na.rm=T), x) # 次に sapply の引数である x が c(4, 3, 4, 3, 1) になります sapply(1:5, \(a, b) sum(a==b, na.rm=T), c(4, 3, 4, 3, 1)) # 無名関数のパラメータとして 1:5 と c(4, 3, 4, 3, 1) が渡されることになりますが、 # パラメータ a にはそれぞれ 1 から 5 まで渡されて、パラメータ b は全て c(4, 3, 4, 3, 1) # になります \(1, c(4, 3, 4, 3, 1)) sum(a==b, na.rm=T) \(2, c(4, 3, 4, 3, 1)) sum(a==b, na.rm=T) \(3, c(4, 3, 4, 3, 1)) sum(a==b, na.rm=T) \(4, c(4, 3, 4, 3, 1)) sum(a==b, na.rm=T) \(5, c(4, 3, 4, 3, 1)) sum(a==b, na.rm=T) # 最終的に以下が実行されることになります sum(1==c(4, 3, 4, 3, 1), na.rm=T) => 1 sum(2==c(4, 3, 4, 3, 1), na.rm=T) => 0 sum(3==c(4, 3, 4, 3, 1), na.rm=T) => 2 sum(4==c(4, 3, 4, 3, 1), na.rm=T) => 2 sum(5==c(4, 3, 4, 3, 1), na.rm=T) => 0 # ここで、数値とベクタを比較すると logical型のベクタが返ります > 1==c(4, 3, 4, 3, 1) [1] FALSE FALSE FALSE FALSE TRUE > 3==c(4, 3, 4, 3, 1) [1] FALSE TRUE FALSE TRUE FALSE # そして sum() 関数では TRUE は整数の 1, FALSE は 0 として集計されます。 > sum(1==c(4, 3, 4, 3, 1)) [1] 1 > sum(3==c(4, 3, 4, 3, 1)) [1] 2

以上の処理が1行目から10行目までのそれぞれの行で実行されます。

投稿2024/07/13 11:02

編集2024/07/14 18:26
melian

総合スコア20574

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

3535_Toucyan

2024/07/14 02:31 編集

meliansa様 ご回答ありがとうございます!試したところ行いたい処理ができ、問題が解決しました! ベストアンサーに選ばせていただきました。 後学のために、コードを確認させてください。 df <- cbind(df, t(apply(df[,2:6], 1, \(x) sapply(1:5, \(a, b) sum(a==b, na.rm=T), x)))) まずはコメントいただいた内容から ①「データフレームの行ごとに(apply(..., 1, ...))」 これはapplyは簡単に各行や列に関数を適用できる。 今回第二引数に1を選択したので、行ごとに第三引数の関数を適用する ②「測定データ(seq(1, 5))の」 これは変数の自動作成で「seq(1,5) = (1:5)」である。 ③「出現回数を集計します(sapply(seq(1, 5), ...))。」 1~5の各列へ合計数を格納している。 というように大まかな流れとしては理解しました。 しかし、具体的にこのコードの記述がなぜこのような結果になるか、細かい部分で、この記述でどのように動作しているのか理解できていませんので、お手すきの際に解説、もしくは理解できる資料、サイトがあればご教示いただけますと幸いです。 下記の部分で理解できておりません。 ①cbindの第二引数、apply前の「t」です。  tは各1~5の作成された列が入る変数を表している? ②「t(apply(df[,2:6],~」」の「df[,2~」でなぜ「,」が必要か?  すでにdfでデータフレームを指定しているので、何の引数を省略しているのでしょうか。 ③バックスラッシュで整数を文字列下していることは分かりました。  「~ \(x) sapply(1:5, \~」のsapplyの前にある「(x)」ですが、  変数列名をつくるための変数?これにより各行の変数を示している? ④「~(a, b) sum(a==b,~」でなぜ、1~5がにaとbに代入されていくのか?  このように前に変数を置く構文がはじめてです。もう少し探してみます。 ⑤「~sum(a==b, na.rm=T), x)~」のxは何をしているのか?  この構文のxに意味することがわかりません。 もしかするとプログラミング的な記述方法かもしれませんが、この辺の知識が不足ていると感じるところです。 apply関数は使ったことがなく、とても勉強になっております。 まだまだコードについて知らないことがあります。 お手数お掛け致しますが、どうぞよろしくお願い致します。
melian

2024/07/14 18:39

追記しました。
3535_Toucyan

2024/07/15 05:52

melian様 分かりやすく、丁寧に追記としてご説明いただき、本当にありがとうございます。 ほとんど理解することが出来ました。細かいところで、まだ少し理解が追い付いていないところもありますが、おそらく自己解決できそうです。 また、困ったときは質問させていただきます。 ほぼないですが、今後私で回答できるものは探してみたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問