微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

R使用combin与apply

如何解决R使用combin与apply

我有一个数据框,其中包含许多变量和观察值的百分比值,如下所示:

obs <- data.frame(Site = c("A","B","C"),X = c(11,22,33),Y = c(44,55,66),Z = c(77,88,99))

我需要将此数据准备为网络分析的边缘列表,以“站点”作为节点,其余变量作为边缘。结果应如下所示:

Node1    Node2    Weight  Type
A         B         33     X
A         C         44     X
...
B         C         187    Z       

因此,对于“ Weight”,我们要计算所有可能的对的总和,并分别针对每一列(以“ Type”结尾)进行计算。

我想答案是必须在apply表达式上使用combn,就像这里的Applying combn() function to data frame一样,但是我还不能完全解决

我可以手工完成“网站”的组合

sites <- combn(obs$Site,2)

然后像这样的各个列

combA <- combn(obs$A,2,function(x) sum(x)

并将这些数据集绑定在一起,但这显然很快变得很烦人。

我试图一次完成所有变量列

b <- apply(newdf[,-1],1,function(x){
sum(utils::combn(x,2))
}
)

但是这有点问题。 有人可以帮忙吗?

解决方法

一种选择是创建一个函数,然后map将该函数应用于您拥有的所有列。

func1 <- function(var){
  obs %>% 
    transmute(Node1 = combn(Site,2)[1,],Node2 = combn(Site,2)[2,Weight = combn(!!sym(var),2,function(x) sum(x)),Type = var)
}

map(colnames(obs)[-1],func1) %>% bind_rows()
,

以下是使用combn

的示例
do.call(
  rbind,combn(1:nrow(obs),FUN = function(k) cbind(data.frame(t(obs[k,1])),stack(data.frame(as.list(colSums(obs[k,-1]))))),simplify = FALSE
  )
)

给出

  X1 X2 values ind
1  A  B     33   X
2  A  B     99   Y
3  A  B    165   Z
4  A  C     44   X
5  A  C    110   Y
6  A  C    176   Z
7  B  C     55   X
8  B  C    121   Y
9  B  C    187   Z
,

尝试一下

library(tidyverse)
obs_long <- obs %>% pivot_longer(-Site,names_to = "type")
sites <- combn(obs$Site,2) %>% t() %>% as_tibble()
Type <- tibble(type = c("X","Y","Z"))

merge(sites,Type) %>% 
  left_join(obs_long,by = c("V1" = "Site","type" = "type")) %>% 
  left_join(obs_long,by = c("V2" = "Site","type" = "type")) %>% 
  mutate(res = value.x + value.y) %>% 
  select(-c(value.x,value.y))


  V1 V2 type res
1  A  B    X  33
2  A  C    X  44
3  B  C    X  55
4  A  B    Y  99
5  A  C    Y 110
6  B  C    Y 121
7  A  B    Z 165
8  A  C    Z 176
9  B  C    Z 187

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。