2016-08-20 8 views
19

長い日付のデータフレームには、同じ日付と人数の複数のエントリがあります。行に重複した識別子でスプレッドを使用する

jj <- data.frame(month=rep(1:3,4), 
      student=rep(c("Amy", "Bob"), each=6), 
      A=c(9, 7, 6, 8, 6, 9, 3, 2, 1, 5, 6, 5), 
      B=c(6, 7, 8, 5, 6, 7, 5, 4, 6, 3, 1, 5)) 

私は広い形式に変換し、このようにそれを作りたい:

month Amy.A Bob.A Amy.B Bob.B 
1  
2  
3 
1 
2 
3 
1 
2 
3 
1 
2 
3 

私の質問はthisと非常によく似ています。私は答えに与えられたコードを使用しています

kk <- jj %>% 
    gather(variable, value, -(month:student)) %>% 
    unite(temp, student, variable) %>% 
    spread(temp, value) 

が、それは誤り以下与える:

Error: Duplicate identifiers for rows (1, 4), (2, 5), (3, 6), (13, 16), (14, 17), (15, 18), (7, 10), (8, 11), (9, 12), (19, 22), (20, 23), (21, 24)

感謝を事前に。 注:複数のエントリを削除したくありません。

+0

出力が意味をなさない。 Bob.Bはどのように5 6 7です。 1月の '5 3'には2つのBob B値がありますか?そして2ヶ月目は「4と2」です。最後に、3月6日に「6 5」。これらを1つの値にまとめています。 –

答えて

14

問題はABの2つの列です。その1つの価値の列を作ることができれば、私たちはあなたが望むようにデータを広めることができます。以下のコードを使用すると、jj_meltの出力を見てください。

library(reshape2) 
jj_melt <- melt(jj, id=c("month", "student")) 
jj_spread <- dcast(jj_melt, month ~ student + variable, value.var="value", fun=sum) 
# month Amy_A Amy_B Bob_A Bob_B 
# 1  1 17 11  8  8 
# 2  2 13 13  8  5 
# 3  3 15 15  6 11 

他の質問がsumによって要約ませんでしたが、data.table答えは、引数を1つ追加して助けることができるので、私は重複としてこれをマークしていないだろう、fun=sum

library(data.table) 
dcast(setDT(jj), month ~ student, value.var=c("A", "B"), fun=sum) 
# month A_sum_Amy A_sum_Bob B_sum_Amy B_sum_Bob 
# 1:  1  17   8  11   8 
# 2:  2  13   8  13   5 
# 3:  3  15   6  15  11 

ご希望の場合tidyrソリューションを使用するには、と組み合わせて要約するとsumとなります。

as.data.frame(jj) 
library(tidyr) 
jj %>% 
    gather(variable, value, -(month:student)) %>% 
    unite(temp, student, variable) %>% 
    dcast(month ~ temp, fun=sum) 
# month Amy_A Amy_B Bob_A Bob_B 
# 1  1 17 11  8  8 
# 2  2 13 13  8  5 
# 3  3 15 15  6 11 

編集あなたの新しい要件に基づいて

、私は活動の列を追加しました。

library(dplyr) 
jj %>% group_by(month, student) %>% 
    mutate(id=1:n()) %>% 
    melt(id=c("month", "id", "student")) %>% 
    dcast(... ~ student + variable, value.var="value") 
# month id Amy_A Amy_B Bob_A Bob_B 
# 1  1 1  9  6  3  5 
# 2  1 2  8  5  5  3 
# 3  2 1  7  7  2  4 
# 4  2 2  6  6  6  1 
# 5  3 1  6  8  1  6 
# 6  3 2  9  7  5  5 

他の溶液も使用することができる。ここで私は、アクティビティ数によって最終的な出力を配置するオプションの式を追加しました:それは、複数のvalue.var列を可能にし、私たちのためにスプレッドの世話をしますので、

library(tidyr) 
jj %>% 
    gather(variable, value, -(month:student)) %>% 
    unite(temp, student, variable) %>% 
    group_by(temp) %>% 
    mutate(id=1:n()) %>% 
    dcast(... ~ temp) %>% 
    arrange(id) 
# month id Amy_A Amy_B Bob_A Bob_B 
# 1  1 1  9  6  3  5 
# 2  2 2  7  7  2  4 
# 3  3 3  6  8  1  6 
# 4  1 4  8  5  5  3 
# 5  2 5  6  6  6  1 
# 6  3 6  9  7  5  5 

data.table構文がコンパクトです。その後、melt -> castプロセスをスキップできます。

library(data.table) 
setDT(jj)[, activityID := rowid(student)] 
dcast(jj, ... ~ student, value.var=c("A", "B")) 
# month activityID A_Amy A_Bob B_Amy B_Bob 
# 1:  1   1  9  3  6  5 
# 2:  1   4  8  5  5  3 
# 3:  2   2  7  2  7  4 
# 4:  2   5  6  6  6  1 
# 5:  3   3  6  1  8  6 
# 6:  3   6  9  5  7  5 
+0

お返事ありがとうございます。私は合計したくありません。算術演算は必要ありません。AmyのA列とB列と、それぞれの値を持つBobのA列とB列を作成したいとします。 –

+1

同じ月、学生、およびクラスの2つの値がある場合、どれを選択しますか? –

+0

私は両方が欲しいです。実際には私は入札を扱っており、データを尋ねているので、複数のエントリがあります。 –

10

あなたの回答に変異IDがありませんでした。ここでは、dplyr packgeのみを使用するソリューションがあります。

jj %>% 
    gather(variable, value, -(month:student)) %>% 
    unite(temp, student, variable) %>% 
    group_by(temp) %>% 
    mutate(id=1:n()) %>% 
    spread(temp, value) 
# A tibble: 6 x 6 
# month id Amy_A Amy_B Bob_A Bob_B 
# * <int> <int> <dbl> <dbl> <dbl> <dbl> 
# 1  1  1  9  6  3  5 
# 2  1  4  8  5  5  3 
# 3  2  2  7  7  2  4 
# 4  2  5  6  6  6  1 
# 5  3  3  6  8  1  6 
# 6  3  6  9  7  5  5 
+0

* id *カラムが不要な場合は、最後に '%>%select(-id)'を追加してください。 – bonna

0
gather(data, key = "key", value = "value", ..., na.rm = FALSE, 
    convert = FALSE, factor_key = FALSE) 

チェックあなたは、キーと値を反転した場合。 "Key"は新しいキーの名前で、 "value"は実際の値です。

関連する問題