【问题标题】:R: Group by / loop through one column of data frameR:分组/循环遍历一列数据框
【发布时间】:2017-08-02 15:00:23
【问题描述】:

我在 R 中有一个数据框 df,这里是它的前 6 行。

df <- data.frame (npi_one = c('n1487','n1952','n1952','n1467','n1467','n1538'),
                  npi_two = c('n1467','n1467','n1487','n1508','n1538','n1508'),
                  weight = c(1,1,2,1,1,1),
                  hee_provn1=c(rep(015171,3),rep(015443,3)))

我想按hee_provn1分组,然后做一个循环,第一个循环的代码是:

library(igraph)
library(dplyr)
library(data.table)

df2 <- filter(df, hee_provn1 == 015171)
df3 <- df2 [,c("npi_one","npi_two")]
l = c(apply(df3,1,c))
G <- graph(l,directed = FALSE)

d <- degree(G)
c <- closeness(G,weight = df2$weight)
b <- betweenness(G, weight = df2$weight)
e <- eigen_centrality(G,weight = df2$weight)$vector

cent_df = data.frame(d,c,b,e)
colnames(cent_df) <- c('degree', 'closeness','betweenness','eigen')
setDT(cent_df, keep.rownames = TRUE)[]
setnames(cent_df,1,"npi")
cbind(hee_provn1 = 015171,cent_df) 

而第一个循环的结果表(hee_provn1 == 015171)是

   hee_provn1   npi degree closeness betweenness     eigen
1:      15171 n1487      2 0.3333333         0.0 1.0000000
2:      15171 n1467      2 0.5000000         0.5 0.7320508
3:      15171 n1952      2 0.3333333         0.0 1.0000000

而第二个循环的结果表(hee_provn1 == 015171)是

   hee_provn1   npi degree closeness betweenness eigen
1:      15443 n1467      2       0.5           0     1
2:      15443 n1508      2       0.5           0     1
3:      15443 n1538      2       0.5           0     1

我是 R 新手,我不知道如何根据数据框的一列进行分组和循环。

另外,我希望我的最终结果是一个大表,将所有表放在一起,例如:

   hee_provn1   npi degree closeness betweenness     eigen
1:      15171 n1487      2 0.3333333         0.0 1.0000000
2:      15171 n1467      2 0.5000000         0.5 0.7320508
3:      15171 n1952      2 0.3333333         0.0 1.0000000
4:      15443 n1467      2       0.5           0     1
5:      15443 n1508      2       0.5           0     1
6:      15443 n1538      2       0.5           0     1

由于某种原因,我不能使用 R 包 tidyverse,谢谢


我尝试了 Balter 的方法,

df <- data.frame (npi_one = c('n1487','n1952','n1952','n1467','n1467','n1538'),
                  npi_two = c('n1467','n1467','n1487','n1508','n1538','n1508'),
                  weight = c(1,1,2,1,1,1),
                  hee_provn1=c(rep(015171,3),rep(015443,3)))

library(igraph)
library(dplyr)
library(data.table)

final.df <- c()
for(x in unique(df$hee_provn1)){
  df2 <- subset(df, subset = hee_provn1 == x)

  df3 <- df2 [,c("npi_one","npi_two")]
  l = c(apply(df3,1,c))
  G <- graph(l,directed = FALSE)

  d <- degree(G)
  c <- closeness(G,weight = df2$weight)
  b <- betweenness(G, weight = df2$weight)
  e <- eigen_centrality(G,weight = df2$weight)$vector

  result <- data.frame(d,c,b,e)
  setDT(result, keep.rownames = TRUE)[]
  setnames(result,1,"npi")
  cbind(hee_provn1 = x,result)
  final.df <- rbind(final.df, result)
}
colnames(final.df) <- c('npi','degree', 'closeness','betweenness','eigen')

结果是:

     npi degree closeness betweenness     eigen
1: n1487      2 0.3333333         0.0 1.0000000
2: n1467      2 0.5000000         0.5 0.7320508
3: n1952      2 0.3333333         0.0 1.0000000
4: n1467      2 0.5000000         0.0 1.0000000
5: n1508      2 0.5000000         0.0 1.0000000
6: n1538      2 0.5000000         0.0 1.0000000

看起来与我的理想结果不同,如何成功跟踪哪个迭代产生了它?

【问题讨论】:

  • 您可以在result 中添加一列。 result &lt;- data.frame(x,d,c,b,e) 因为 x 是您要细分的内容。不要忘记更改最后一行:colnames(final.df) &lt;- c('hee_provn1','npi','degree', 'closeness','betweenness','eigen')
  • 仅供参考,您的cbind(hee_provn1 = x,result) 行不执行任何操作。您需要分配结果。只有特殊的set* 函数在不分配结果的情况下工作。此外,在 R 中,在循环中动态增长的东西效率很低。R Inferno 是一个很好的指南,可以很好地解决像这样的陷阱burns-stat.com/documents/books/the-r-inferno

标签: r loops dataframe


【解决方案1】:

在不加载 dplyr 的情况下重新开始。那么……

library(data.table)
library(igraph)
setDT(df)

# clean bad formatting
df[, `:=`(npi_one = as.character(npi_one), npi_two = as.character(npi_two))]

df[, {
  G = graph_from_edgelist(cbind(npi_one, npi_two), directed = FALSE)
  .(
    v = V(G)$name,
    d = degree(G),
    c = closeness(G, weight = weight),
    b = betweenness(G, weight = weight),
    e = eigen_centrality(G, weight = weight)$vector
  )
}, by=hee_provn1]

这给...

   hee_provn1     v d         c   b         e
1:      15171 n1487 2 0.3333333 0.0 1.0000000
2:      15171 n1467 2 0.5000000 0.5 0.7320508
3:      15171 n1952 2 0.3333333 0.0 1.0000000
4:      15443 n1467 2 0.5000000 0.0 1.0000000
5:      15443 n1508 2 0.5000000 0.0 1.0000000
6:      15443 n1538 2 0.5000000 0.0 1.0000000

它是如何工作的

Data.table 语法是DT[i, j, by=],它按i 过滤(此处不需要),按by= 分组,然后计算jj 应该计算为一个列表,list() 可以写成 .() 作为简写。

为什么不加载 dplyr?这不是必需的,并且 igraph 已经有足够的命名空间冲突。


如果你真的要使用dplyr,我强烈建议不要同时使用data.table...

library(dplyr)
library(magrittr)
library(igraph)

# fix bad formatting
df %<>% mutate(npi_one = as.character(npi_one), npi_two = as.character(npi_two))

df %>% group_by(hee_provn1) %>% do(with(., {
  G = graph_from_edgelist(cbind(npi_one, npi_two), directed = FALSE)
  data.frame(
    v = V(G)$name,
    d = degree(G),
    c = closeness(G, weight = weight),
    b = betweenness(G, weight = weight),
    e = eigen_centrality(G, weight = weight)$vector
  )
}))

# A tibble: 6 x 6
# Groups:   hee_provn1 [2]
  hee_provn1     v     d         c     b         e
       <dbl> <chr> <dbl>     <dbl> <dbl>     <dbl>
1      15171 n1487     2 0.3333333   0.0 1.0000000
2      15171 n1467     2 0.5000000   0.5 0.7320508
3      15171 n1952     2 0.3333333   0.0 1.0000000
4      15443 n1467     2 0.5000000   0.0 1.0000000
5      15443 n1508     2 0.5000000   0.0 1.0000000
6      15443 n1538     2 0.5000000   0.0 1.0000000

【讨论】:

  • 嗨,弗兰克,如果可能的话,你能告诉我使用 dplyr 的代码吗?
  • @kkjoe 好的,已添加。
  • 谢谢你,弗兰克。抱歉,我刚刚发现我们的结果不同。如果你看 15443,n1467,你会发现你的接近度是 0.1666667,然而,你可以很容易地发现图 15543 是一个所有权重为 1 的三角形结构,所以 n1467 的度量应该与 n1538 以及 n1508 相同。我非常努力地研究了你的代码,但不知道为什么
  • @kkjoe Op,对此感到抱歉。我应该使用graph_from_edgelist,而不是graph。我已经在帖子中修复了它,现在它似乎匹配了。
  • 谢谢您,先生,现在看起来很完美。我提出了一个新问题,它增加了一个新的需求——从另一个表中添加一些单个节点。你非常擅长 r 数据框,如果你能帮我解决这个问题,我将非常感激,使用 dyplr,而不是循环。谢谢你 ! stackoverflow.com/questions/46185154/…,
【解决方案2】:

我能想到的最简单的方法(无需重新创建整个代码):

final.df <- c()
for(x in unique(df$hee_provn1)){
  y <- subset(df, subset = hee_provn1 == x)
  result <- ##do your stuff here with table y
 final.df <- rbind(final.df, result)
}

因此,您为 hee_provn1 中的每个唯一值设置表的子集,完成您的工作,然后将结果附加到数据框。

【讨论】:

  • 我试过你的方法,很酷,我在问题中更新了它,但我仍然不知道如何跟踪哪个迭代产生了结果。谢谢
  • 我评论了你原来的问题:)
  • 我已经在 OP 下对此发表了评论,但您可能想看看 R Inferno 的第 2 章 burns-stat.com/documents/books/the-r-inferno 这可能违反直觉,但在使用 R 编程时记住这一点很有用.
猜你喜欢
  • 2018-09-28
  • 1970-01-01
  • 2021-02-08
  • 1970-01-01
  • 2018-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多