如何使用dplyr/tidyr
来转换数据框,如下所示:
df <- data.frame(obj=c(1,1,2,2,3,3,3,4,4,4),
S1=rep(c("a","b"),length.out=10),S1PR=rep(c(3,7),length.out=10),
S2=rep(c("c","d"),length.out=10),S2PR=rep(c(7,3),length.out=10),
Relsize=c(.4,.6,.4,.6,.2,.2,.6,.2,.2,.6))
obj S1 S1PR S2 S2PR Relsize
1 1 a 3 c 7 0.4
2 1 b 7 d 3 0.6
3 2 a 3 c 7 0.4
4 2 b 7 d 3 0.6
5 3 a 3 c 7 0.2
6 3 b 7 d 3 0.2
7 3 a 3 c 7 0.6
8 4 b 7 d 3 0.2
9 4 a 3 c 7 0.2
10 4 b 7 d 3 0.6
然后把它变成这样的一个:
obj a b c d
1 0.12 0.42 0.28 0.18
2 0.12 0.42 0.28 0.18
3 0.24 0.14 0.56 0.06
输出数据框中的值基于PR / 10 * Relsize。编辑:对于同一物种有多个条目,他们应该总结我一直试图通过传播和聚集的一些组合来做这个,但我不知道该怎么做。
答案 0 :(得分:1)
使用基数R:
df <- data.frame(stringsAsFactors = F,obj=c(1,1,2,2,3,3,3,4,4,4),
S1=rep(c("a","b"),length.out=10),S1PR=rep(c(3,7),length.out=10),
S2=rep(c("c","d"),length.out=10),S2PR=rep(c(7,3),length.out=10))
df$Relsize=c(0.4,0.6,.4,.6,.2,.2,.6,.2,.2,.6)
#Create the next two columns required:. I will call them `oo and pp`
df1=transform(df,oo=S1PR*Relsize/10,pp=S2PR*Relsize/10)
按列obj,s1 and s2
进行分组并对oo and pp
执行总和,我们使用aggregate
m=aggregate(.~obj+S1+S2,df1,sum)#aggregate(cbind(oo,pp)~obj+S1+S2,df1,sum)
现在重新排列结果数据帧,如图所示,列S1,S2
的内容应该是新的列名,而oo,pp
的内容应该在这些列中传播。我们使用unstack
unstack(m,cbind(oo,pp)~cbind(S1,S2))
a b c d
1 0.12 0.42 0.28 0.18
2 0.12 0.42 0.28 0.18
3 0.24 0.14 0.56 0.06
4 0.06 0.56 0.14 0.24
答案 1 :(得分:1)
另一种选择可能是使用reshape2
中的library(tidyverse)
library(reshape2)
df_mod <- df %>%
mutate(S1PR = (S1PR/10)*Relsize,
S2PR = (S2PR/10)*Relsize) %>%
select(-Relsize)
bind_rows(x = select(df_mod,obj, S := S1, PR := S1PR),
y = select(df_mod, obj, S := S2, PR :=S2PR)) %>%
dcast(obj ~ S, sum)
# obj a b c d
#1 1 0.12 0.42 0.28 0.18
#2 2 0.12 0.42 0.28 0.18
#3 3 0.24 0.14 0.56 0.06
#4 4 0.06 0.56 0.14 0.24
到达:
df <- data.frame(obj=c(1,1,2,2,3,3,3,4,4,4),
S1=rep(c("a","b"),length.out=10),S1PR=rep(c(3,7),length.out=10),
S2=rep(c("c","d"),length.out=10),S2PR=rep(c(7,3),length.out=10),
Relsize=c(.4, .6, .4, .6, .2, .2, .6, .2, .2, .6),
stringsAsFactors = FALSE)
数据
{{1}}
答案 2 :(得分:1)
使用dplyr和tidyr,但与MKR的解决方案相同。
OP没有说明求和是否正确。
也许bind_rows
可能更优雅但似乎到目前为止所有的建议都做了类似的事情。
df %>%
as_data_frame %>%
mutate(Relsize=c(0.4,0.6,.4,.6,.2,.2,.6,.2,.2,.6)) %>%
mutate(S1PR = (S1PR/10)*Relsize, S2PR = (S2PR/10)*Relsize) %>%
{bind_rows(select(., obj, S = S1, PR = S1PR),
select(., obj, S = S2, PR = S2PR)
)
} %>%
group_by(obj, S) %>%
summarise(PR=sum(PR)) %>%
spread(S, PR)
答案 3 :(得分:0)
我想出了一种避免使用bind_rows
df %>%
unite(S1_S1PR, contains("S1")) %>%
unite(S2_S2PR, contains("S2")) %>%
gather(x, Species, S1_S1PR, S2_S2PR) %>%
separate(Species, into = c("Species","PR"), convert = T) %>%
group_by(obj, Species) %>%
mutate(PR = sum(PR/10*Relsize)) %>%
select(-x, -Relsize) %>% distinct() %>%
spread(Species, PR)
它更具可读性,但需要更多步骤。我发现我经常在生态学中看到这样的数据,其中每一行都是一个位置,并且有一组像SX和SXPR这样的列,它们被重复用于该位置的第一,第二和第三最常见的物种。能够使用dplyr的漂亮选择助手获得所有匹配的列对于许多列非常有用