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

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

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

RStudioは、Rのプログラミングを効率化する統合開発環境です。統計計算とグラフィックスができるプログラミング言語であるRのIDEでOSSで公開されています。ソースコードやコンソールなどが一つの画面に見やすく配置されている点が特徴。コマンド名以外に、関数名やパッケージ名も補完できます。

R

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

Q&A

2回答

425閲覧

そのグループの要素の変数の内一つでも共有していれば同じグループに分類したい。

maltines

総合スコア12

RStudio

RStudioは、Rのプログラミングを効率化する統合開発環境です。統計計算とグラフィックスができるプログラミング言語であるRのIDEでOSSで公開されています。ソースコードやコンソールなどが一つの画面に見やすく配置されている点が特徴。コマンド名以外に、関数名やパッケージ名も補完できます。

R

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

0グッド

0クリップ

投稿2023/12/25 11:39

編集2023/12/26 05:39

実現したいこと

  • そのグループの変数の内、自分の変数と同じ数字を一つでも共有していれば同じグループに分類したい。

前提

以下のようなデータがあるとします。

R

1data <- data.frame( 2 V1 = c(1, 1, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 7), 3 V2 = c(1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 5, 6, 7), 4 V3 = c(1, 1, 1, 2, 3, 4, 5, 5, 6, 5, 6, 7, 8) 5) 6 7>print(data) 8 V1 V2 V3 91 1 1 1 102 1 2 1 113 2 2 1 124 3 3 2 135 3 3 3 146 4 4 4 157 4 4 5 168 4 5 5 179 4 5 6 1810 5 5 5 1911 5 5 6 2012 6 6 7 2113 7 7 8

このデータをグループ化する新たな変数を作りたいです。
具体的には、第1変数、第2変数、第3変数、どれか一つでもあるグループの行と同じだと、同じグループとしたいです。つまり、「自分以外のグループの構成員の内誰か一人でも変数のどれかを共有している」という条件です。逆に言えば、第1変数、第2変数、第3変数の全てにおいてそのグループのどの行とも共有しない場合、異なるグループとしたいです。例えば、上記のデータをこの規則に従ってグループ化(第4変数)すると、以下のようなものになります。

R

1>print(data) 2 V1 V2 V3 Group 31 1 1 1 1 42 1 2 1 1 53 2 2 1 1 64 3 3 2 2 75 3 3 3 2 86 4 4 4 3 97 4 4 5 3 108 4 5 5 3 119 4 5 6 3 1210 5 5 5 3 1311 5 5 6 3 1412 6 6 7 4 1513 7 7 8 5

これを実現するコードが無知ゆえに見当が付きません。各変数ではグループ化(tidyverseなどによるもの)は当然できるが、各変数グループの論理和的なグルーピングのコードがどうやっても思いつかないため、大変申し訳ないが知恵をお借りしたいです。

調査したこと・試したこと

以下のコードを実行しましたが、思った出力にはなりませんでした。

R

1data <- data.frame( 2 V1 = c(1, 1, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 7), 3 V2 = c(1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 5, 6, 7), 4 V3 = c(1, 1, 1, 2, 3, 4, 5, 5, 6, 5, 6, 7, 8) 5) 6 7data <- data %>% 8 group_by(V1|V2|V3) %>% 9 mutate(group_id = group_indices()) 10 11print(data) 12 13> print(data) 14# A tibble: 13 × 5 15# Groups: V1 | V2 | V3 [1] 16 V1 V2 V3 `V1 | V2 | V3` group_id 17 <dbl> <dbl> <dbl> <lgl> <int> 18 1 1 1 1 TRUE 1 19 2 1 2 1 TRUE 1 20 3 2 2 1 TRUE 1 21 4 3 3 2 TRUE 1 22 5 3 3 3 TRUE 1 23 6 4 4 4 TRUE 1 24 7 4 4 5 TRUE 1 25 8 4 5 5 TRUE 1 26 9 4 5 6 TRUE 1 2710 5 5 5 TRUE 1 2811 5 5 6 TRUE 1 2912 6 6 7 TRUE 1 3013 7 7 8 TRUE 1

単純に論理和をグルーピングに入れるだけでは理想の出力になりません。(そりゃそうですが。)
しかし、これ以外に思いつきません。

補足情報(FW/ツールのバージョンなど)

Rstudioは3か月前に更新したもの。OSはwindows11。

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

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

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

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

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

maltines

2023/12/25 13:09

失礼いたしました。記入しました。
guest

回答2

0

igraph パッケージ を用い,データの各行を頂点とする無向グラフを使ってグループ分けする記述例を下記に示します。

  • 隣接行列(w)を用意し,両頂点が「3変数のどれかを共有しているか否か」で「10 」を(無向グラフに必要な左下三角部分に)格納する

  • 隣接行列(w)から無向グラフ(g)を作成する

  • 関数 components(g) が出力する membership ベクトルを group_id として data に追加する

R

1library(igraph) 2 3data <- data.frame( 4 V1 = c(1, 1, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 7), 5 V2 = c(1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 5, 6, 7), 6 V3 = c(1, 1, 1, 2, 3, 4, 5, 5, 6, 5, 6, 7, 8)) 7 8N <- nrow(data) 9w <- matrix(0, nrow=N, ncol=N) 10for (i in 2:N) { 11 for (j in 1:i-1) { 12 w[i, j] <- ifelse(any(data$V1[i] == data$V1[j], 13 data$V2[i] == data$V2[j], 14 data$V3[i] == data$V3[j]), 15 1, 0) 16 } 17} 18 19g <- graph_from_adjacency_matrix(w, mode="lower") 20data$group_id <- components(g)$membership 21 22print(data) 23## V1 V2 V3 group_id 24## 1 1 1 1 1 25## 2 1 2 1 1 26## 3 2 2 1 1 27## 4 3 3 2 2 28## 5 3 3 3 2 29## 6 4 4 4 3 30## 7 4 4 5 3 31## 8 4 5 5 3 32## 9 4 5 6 3 33## 10 5 5 5 3 34## 11 5 5 6 3 35## 12 6 6 7 4 36## 13 7 7 8 5

投稿2023/12/29 14:31

編集2023/12/30 04:57
little_street

総合スコア319

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

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

0

r

1suppressMessages(library(tidyverse)) 2 3data <- data.frame( 4 V1 = c(1, 1, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 7), 5 V2 = c(1, 2, 2, 3, 3, 4, 4, 5, 5, 5, 5, 6, 7), 6 V3 = c(1, 1, 1, 2, 3, 4, 5, 5, 6, 5, 6, 7, 8) 7) 8 9data %>% 10 rowwise() %>% 11 mutate(group_id = list(which(colSums(c_across(everything()) == t(.)) > 0))) %>% 12 mutate(group_id = 13 reduce(.$group_id, 14 ~{ s <- intersect(unlist(.x), .y); ifelse(length(s), list(s), .x) }, 15 .init=list(group_id))) %>% 16 group_by(group_id) %>% 17 mutate(group_id = cur_group_id()) -> data 18 19data 20 21# # A tibble: 13 × 4 22# # Groups: group_id [5] 23# V1 V2 V3 group_id 24# <dbl> <dbl> <dbl> <int> 25# 1 1 1 1 1 26# 2 1 2 1 1 27# 3 2 2 1 1 28# 4 3 3 2 2 29# 5 3 3 3 2 30# 6 4 4 4 3 31# 7 4 4 5 3 32# 8 4 5 5 3 33# 9 4 5 6 3 34# 10 5 5 5 3 35# 11 5 5 6 3 36# 12 6 6 7 4 37# 13 7 7 8 5

投稿2023/12/26 03:49

編集2023/12/26 17:48
melian

総合スコア19825

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

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

maltines

2023/12/26 05:30 編集

申し訳ございません、説明が不十分でした。修正いたしました。 グループに入る条件としては、「グループの構成員の内誰か一人でも変数のどれかを共有している。」です。(説明の便宜上、行数を構成員のIDとみなしています。) そのため、6-11行目は全て同じグループに属します。 例えば、6行目の4,4,4と、11行目の5,5,6の二人はたしかにどの変数も数字を共有していませんが、8行目の4,5,5や9行目の4,5,6を介して数字を共有しているため、6行目と11行目は同一グループとみなされます。(イメージ的には、6行目-8行目-11行目、または6行目-9行目-11行目のように繋がっている) 逆に、グループが異なれば、数字を共有するどの人を介しても違うグループの人を同じグループに出来ません。 例えば、グループ2の4行目3,3,2は、5行目3,3,3以外には直接的にも間接的にも繋がれません。 想定出力のグループは、このように直接的でなく間接的にも繋がることが出来る場合も考慮されています。
melian

2023/12/26 17:10

書き直してみました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問