为了账号安全,请及时绑定邮箱和手机立即绑定

对行使用重复标识符的点差

/ 猿问

对行使用重复标识符的点差

侃侃无极 2019-11-19 10:32:56

我有一个长格式的数据框,其中包含相同日期和人的多个条目。


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

我的问题与此非常相似。我已经在答案中使用了给定的代码:


kk <- jj %>% 

  gather(variable, value, -(month:student)) %>% 

  unite(temp, student, variable) %>% 

  spread(temp, value)

但它给出以下错误:


错误:行(1、4),(2、5),(3、6),(13、16),(14、17),(15、18),(7、10),(8)的标识符重复,11),(9,12),(19,22),(20,23),(21,24)


提前致谢。注意:我不想删除多个条目。


查看完整描述

3 回答

?
天涯尽头无女友

问题是两个两列A和B。如果我们可以创建一个值列,那么我们可以根据需要分配数据。查看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答案可以帮助增加一个参数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解决方案,结合它dcast的总结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

也可以使用其他解决方案。在这里,我添加了一个可选表达式,以按活动编号排列最终输出:


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语法是紧凑的,因为它允许多个value.var列,会照顾蔓延的我们。然后我们可以跳过该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


查看完整回答
反对 回复 2019-11-19
?
回首忆惘然

您的答案缺少mutate 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


查看完整回答
反对 回复 2019-11-19
?
慕妹3242003

由于建议使用tidyr 1.0.0 pivot_wider替代,spread因此您可以执行以下操作:


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))


library(tidyr)


pivot_wider(

  jj,

  names_from = "student",

  values_from = c("A","B"),

  names_sep = ".",

  values_fn = list(A= list, B= list)) %>%

  unchop(everything())

#> # A tibble: 6 x 5

#>   month A.Amy A.Bob B.Amy B.Bob

#>   <int> <dbl> <dbl> <dbl> <dbl>

#> 1     1     9     3     6     5

#> 2     1     8     5     5     3

#> 3     2     7     2     7     4

#> 4     2     6     6     6     1

#> 5     3     6     1     8     6

#> 6     3     9     5     7     5

由reprex软件包(v0.3.0)创建于2019-09-14


这个问题的转折点在于学生不是一个月唯一的人,可以解决这个问题:


values_fn = list(A= list, B= list)) 将多个值放在列表中

unchop(everything())垂直嵌套列表,您也可以unnest在这里使用


查看完整回答
反对 回复 2019-11-19
  • 3 回答
  • 0 关注
  • 40 浏览
我要回答

相关问题推荐

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信