在R中重新排列数据框的列(使用mutate和dplyr)。

5
我有一个类似于数据框的数据结构。
Type  Number  Species
A     1         G    
A     2         R 
A     7         Q
A     4         L
B     4         S
B     5         T
B     3         H
B     9         P
C     12        K
C     11        T
C     6         U
C     5         Q

我在哪里使用了group_by(Type) 我的目标是通过将NUMBER列中的前2个值合并来折叠这些数据,然后创建一个新列(Number_2),该列包含第二个2个值。 此外,我希望删除底部两个数字对应的物种值,以便该物种对应行中更高的数字 我想使用dplyr,最终结果如下

Type  Number Number_2   Species       
A     7    1               Q
A     4    2               L 
B     5    3               T
B     9    4               P
C     12   6               K
C     11   5               T

目前,number_2所在的顺序并不重要,只要它与其他同类型的元素相同即可... 我不知道这是否可能,如果可能,有人知道如何实现吗...

谢谢!


抱歉,我的意思是更改自己的数据,而不是更改这个问题! - user4999605
3个回答

7
你可以尝试一下。
library(data.table)
setDT(df1)[order(-Number), list(Number1=Number[1:2], 
                                Number2=Number[3:4],
                                Species=Species[1:2]), keyby = Type]
 #   Type Number1 Number2 Species
 #1:    A       7       2       Q
 #2:    A       4       1       L
 #3:    B       9       4       P
 #4:    B       5       3       T
 #5:    C      12       6       K
 #6:    C      11       5       T

或者使用dplyrdo
 library(dplyr)
 df1 %>% 
   group_by(Type) %>%
   arrange(desc(Number)) %>%
   do(data.frame(Type=.$Type[1L],
                Number1=.$Number[1:2], 
                Number2 = .$Number[3:4],
                Species=.$Species[1:2], stringsAsFactors=FALSE))
 #   Type Number1 Number2 Species
 #1    A       7       2       Q
 #2    A       4       1       L
 #3    B       9       4       P
 #4    B       5       3       T
 #5    C      12       6       K
 #6    C      11       5       T

我在帖子中添加了一条编辑内容,您能否再看一下 -- 谢谢! - user4999605
2
我正要发表同样的观点,因为我认为这不能简单地通过 dplyr 完成。顺便说一下,你不需要 [order(Type)],只需使用 keyby 替换 by 即可。 - David Arenburg
@DavidArenburg 我用 dplyr 发布了一个解决方案。你是对的。它有点太复杂了。 - akrun
2
似乎可以创建一个 c(1,1,2,2) 变量,然后使用 dcast,但我没有这方面的技能或工具。在 Arun 的新幻灯片上看到了类似的东西(搜索 "dcast"):https://github.com/Rdatatable/data.table/wiki/talks/ArunSrinivasanUseR2015.pdf,从 dplyr 中的 do 看起来总是不太好。 - Frank
1
很棒的答案!这就是我们所说的“简单明了” :-)。您可能想使用(.N-1):.N(或使用tail())代替硬编码为3:4,但这只是小问题。 - Arun
显示剩余2条评论

2
这里提供了一种不同的dplyr方法。
library(dplyr)

# Start creating the data set with top 2 values and store as df1:
df1 <- df %>% 
  group_by(Type) %>%
  top_n(2, Number) %>%
  ungroup() %>%
  arrange(Type, Number)

# Then, get the anti-joined data (the not top 2 values), arrange, rename and select
# the number colummn and cbind to df1:
out <- df %>%
  anti_join(df1, c("Type","Number")) %>%
  arrange(Type, Number) %>%
  select(Number2 = Number) %>%
  cbind(df1, .)

这将导致:
> out
#  Type Number Species Number2
#1    A      4       L       1
#2    A      7       Q       2
#3    B      5       T       3
#4    B      9       P       4
#5    C     11       T       5
#6    C     12       K       6

2
这可能是使用ddply的另一种选择。
library(plyr)
ddply(dat[order(Number)], .(Type), summarize, 
      Number1 = Number[4:3],  Number2 = Number[2:1], Species = Species[4:3])

#  Type Number1 Number2 Species
#1    A       7       2       Q
#2    A       4       1       L
#3    B       9       4       P
#4    B       5       3       T
#5    C      12       6       K
#6    C      11       5       T

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接