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

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

ただいまの
回答率

89.52%

データフレームのセルの中のリストをgatherしたい

受付中

回答 4

投稿

  • 評価
  • クリップ 0
  • VIEW 1,018

jackojacko_

score 15

> DT
   id         comment
1:  1 mary,hello,hoge
2:  2       bob,world


このようなデータフレームを、以下のように変形したいです。
なおcommentの中は文字列のリスト(c("mary","hello","hoge"))になっています。

> DT
   id  comment
1:  1  mary
2:  1  hello
3:  1  hoge
2:  2  bob
2:  2  world


最悪for文を回せばできるのですが、tidyrのgatherのような感じで効率的に出来る方法があれば、是非ご教授願いたいです。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

0

これでどうでしょう。なお「commentの中は文字列のリスト(c("mary","hello","hoge"))」とのことですが、そのようなdata.frameは作れないと思うので、単純にコンマ区切りの文字列であると仮定しています。

df1 <- read.table(
  text="
   id comment
    1 mary,hello,hoge
    2 bob,world
  ",
  header=T,
  stringsAsFactors = F
)

l <- strsplit(df1$comment, ",")
df2 <- data.frame(
  id     = rep(df1$id, sapply(l, length)),
  comment= unlist(l)
)

print(df1)
print(df2)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

効率的かどうかはさておき、形だけ合っていれば良いのなら以下のような感じでどうでしょう。

# 処理前
> DT
  id           comment
1  1 mary, hello, hoge
2  2        bob, world
> str(DT)
'data.frame':    2 obs. of  2 variables:
 $ id     : int  1 2
 $ comment:List of 2
  ..$ : chr  "mary" "hello" "hoge"
  ..$ : chr  "bob" "world"


library(reshape2)
DT2 <- melt(DT$comment)
names(DT2) <- c("comment", "id")
DT2 <- DT2[,c(2,1)]
DT2$comment <- as.character(DT2$comment)


# 処理後
> DT2
  id comment
1  1    mary
2  1   hello
3  1    hoge
4  2     bob
5  2   world
> str(DT2)
'data.frame':    5 obs. of  2 variables:
 $ id     : int  1 1 1 2 2
 $ comment: chr  "mary" "hello" "hoge" "bob" ...

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

少し長いですが、tidyverse でやるならこんな感じだと思います。
(もう少し上手くやる方法はあると思いますが)

# データの作成
df <- tibble(id = c(1, 2),
       comment = c("mary,hello,hoge", "bob,world"))

# 分割後のコメントがいくつ必要かを計算するために、各行の","の数を計算
df <- df %>% 
  mutate(count = str_count(comment, ","))

# 分割後の最大コメント数を計算
max_col <- (df$count %>% max()) + 1

df %>% 
  # count はもう使わないので捨てる
  select(-count) %>% 
  # comment を "," で分ける
  separate(comment, 
           # 分けた先の列名を指定
           into = str_c("col", 1:max_col),
           sep = ",") %>% 
  # gather で縦長に変換
  gather(key = col, value = comment, -id) %>% 
  # col がいらないので捨てる
  select(-col) %>% 
  # NA が混ざっているので除去する
  filter(!is.na(comment)) %>% 
  # 並び替える
  arrange(id, comment)
tibble: 5 x 2
     id comment
  <dbl> <chr>  
1     1 hello  
2     1 hoge   
3     1 mary   
4     2 bob    
5     2 world  

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

comment列を一気にばらす方法です
具体的には入れ子状とみて、nest化→map関数で","のところで分割→元に戻す方法です。遠回りです。
分割のときにちょうどいい列数を組めたら楽になるかもしれません。

library(tidyverse)

DT %>%
    #comment列を入れ子にする
    tidyr::nest(-id) %>%
    #入れ子の2行に対してseparate関数で列を分割する
    dplyr::mutate(model = dplyr::map(data, ~ separate(., col = comment, into = c("a", "b", "c"), sep = ","))) %>% 
    #入れ子を解除する。comment列が分割された状態で出てくる
    tidyr::unnest() %>%
    dplyr::select(-comment) %>%
    tidyr::gather(key, value, -id) %>%
    dplyr::filter(!is.na(value))

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 89.52%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる