dplyr中分组的多个变量之间的相关性

时间:2018-12-13 15:13:13

标签: r dplyr correlation

说我有一个数据框,像这样:

# Set RNG seed
set.seed(33550336)

# Create dummy data frame
df <- data.frame(PC1 = runif(20),
                 PC2 = runif(20),
                 PC3 = runif(20),
                 A = runif(20),
                 B = runif(20),
                 loc = sample(LETTERS[1:2], 20, replace = TRUE),
                 seas = sample(c("W", "S"), 20, replace = TRUE))

# > head(df)
#         PC1        PC2       PC3         A         B loc seas
# 1 0.8636470 0.02220823 0.7553348 0.4679607 0.0787467   A    S
# 2 0.3522257 0.42733152 0.2412971 0.6691419 0.1194121   A    W
# 3 0.5257408 0.44293320 0.3225228 0.0934192 0.2966507   B    S
# 4 0.0667227 0.90273594 0.6297959 0.1962124 0.4894373   A    W
# 5 0.3751383 0.50477920 0.6567203 0.4510632 0.4742191   B    S
# 6 0.9197086 0.32024904 0.8382138 0.9907894 0.9335657   A    S

我对计算PC1PC2PC3与按{{1分组的每个变量AB之间的相关性感兴趣}}和loc。因此,例如,基于this answer,我可以执行以下操作:

seas

这给了我我想要的:# Correlation of variable A and PC1 per loc & seas combination df %>% group_by(loc, seas) %>% summarise(cor = cor(PC1, A)) %>% ungroup # # A tibble: 4 x 3 # loc seas cor # <fct> <fct> <dbl> # 1 A S 0.458 # 2 A W 0.748 # 3 B S -0.0178 # 4 B W -0.450 PC1的每种组合在Aloc之间的相关性。 很棒

我正在努力进行的工作是对seas变量和其他变量(在示例中为PC*A)的每种组合进行推断以执行计算。我的预期结果是上面的小标题,但是B和其他变量的每个组合都有一列。我可以做很多事情... PC*cor(PC2, A)cor(PC3, A)等,但是大概有一种简洁的编码计算方法。我怀疑它牵涉到cor(PC1, B),但我不能完全理解……有人可以启发我吗?


解决方案

我选择了格罗腾迪克(G. Grothendieck)的solution below,但这需要进行一些重组才能将其转换为所需的格式。我已经发布了我在这里使用的代码,以防其他人使用它。

do

给出,

# Perform calculation
res <- by(df[1:5], df[-(1:5)], cor)

# Combinations of loc & seas 
comb <- expand.grid(dimnames(res))

#   loc seas
# 1   A    S
# 2   B    S
# 3   A    W
# 4   B    W

# A matrix corresponding to a loc & seas
# Plus the loc & seas themselves
restructure <- function(m, n){
  # Convert to data frame
  # Add rownames as column
  # Retains PCs as rows, but not columns
  # Gather variables to long format
  # Unite PC & variable names
  # Spread to a single row
  # Add combination of loc & seas
  m %>% 
    data.frame %>% 
    rownames_to_column() %>% 
    filter(grepl("PC", rownames(m))) %>% 
    select(-contains("PC")) %>% 
    gather(variable, value, -rowname) %>% 
    unite(comb, rowname, variable) %>% 
    spread(comb, value) %>% 
    bind_cols(n)
}

# Restructure each list element & combine into data frame
do.call(rbind, lapply(1:length(res), function(x)restructure(res[[x]], comb[x, ])))

3 个答案:

答案 0 :(得分:7)

像这样使用// Copy assets to out dir. Add your own globs as needed. new CopyWebpackPlugin([ { from: "fonts/**" }, { from: "**/*.jpg" }, { from: "**/*.png" }, { from: "assets/**" }, // Add your asset folder path like this ], { ignore: [`${relative(appPath, appResourcesFullPath)}/**`] }),

by

给予:

By <- by(df[1:5], df[-(1:5)], cor)

添加

根据发布者对所需内容的进一步讨论,定义> By loc: A seas: S PC1 PC2 PC3 A B PC1 1.00000000 -0.3941583 0.1872622 0.4576316 -0.00925106 PC2 -0.39415826 1.0000000 -0.6797708 0.3522161 0.20916667 PC3 0.18726218 -0.6797708 1.0000000 -0.2003091 0.37414025 A 0.45763159 0.3522161 -0.2003091 1.0000000 0.57292305 B -0.00925106 0.2091667 0.3741403 0.5729230 1.00000000 ----------------------------------------------------------------------------------------------------------------------------- loc: B seas: S PC1 PC2 PC3 A B PC1 1.00000000 -0.52651449 0.07120701 -0.01779813 -0.7432814 PC2 -0.52651449 1.00000000 -0.05448583 -0.35011878 0.4632416 PC3 0.07120701 -0.05448583 1.00000000 0.80342399 0.4580262 A -0.01779813 -0.35011878 0.80342399 1.00000000 0.5558740 B -0.74328144 0.46324158 0.45802622 0.55587404 1.0000000 ----------------------------------------------------------------------------------------------------------------------------- loc: A seas: W PC1 PC2 PC3 A B PC1 1.0000000 -0.79784422 0.0932317 0.7483545 0.49639477 PC2 -0.7978442 1.00000000 -0.3526315 -0.3994917 -0.05233889 PC3 0.0932317 -0.35263151 1.0000000 -0.5902400 0.36066898 A 0.7483545 -0.39949171 -0.5902400 1.0000000 0.18081316 B 0.4963948 -0.05233889 0.3606690 0.1808132 1.00000000 ----------------------------------------------------------------------------------------------------------------------------- loc: B seas: W PC1 PC2 PC3 A B PC1 1.0000000 0.3441459 0.1135686 -0.4502518 -0.6672104 PC2 0.3441459 1.0000000 -0.8447551 -0.9899521 -0.8098906 PC3 0.1135686 -0.8447551 1.0000000 0.7606430 0.3738706 A -0.4502518 -0.9899521 0.7606430 1.0000000 0.8832408 B -0.6672104 -0.8098906 0.3738706 0.8832408 1.0000000 函数,该函数接受相关矩阵或数据帧(在后一种情况下,它将前5列转换为相关矩阵),产生一行输出。对于onerow代码行,if中的onerow语句不是必需的,但不会受到伤害,但是我们已经包含了它,因此adply也可以在一个简单的环境中工作在下面的后续示例中也是如此。

onerow

给予:

library(plyr)

onerow <- function(x) {
  if (is.data.frame(x)) x <- cor(x[1:5])
  dtab <- as.data.frame.table(x[4:5, 1:3])
  with(dtab, setNames(Freq, paste(Var2, Var1, sep = "_")))
}

adply(By, 1:2, onerow)

或者完全摆脱 loc seas PC1_A PC1_B PC2_A PC2_B PC3_A PC3_B 1 A S 0.45763159 -0.00925106 0.3522161 0.20916667 -0.2003091 0.3741403 2 B S -0.01779813 -0.74328144 -0.3501188 0.46324158 0.8034240 0.4580262 3 A W 0.74835455 0.49639477 -0.3994917 -0.05233889 -0.5902400 0.3606690 4 B W -0.45025181 -0.66721038 -0.9899521 -0.80989058 0.7606430 0.3738706 ,并使用它给出相同的输出:

by

或使用dplyr:

library(plyr)
ddply(df, -(1:5), onerow)

答案 1 :(得分:3)

这是通过[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class MyActionFilterAttribute : ActionFilterAttribute { public override void OnActionExecuting(HttpActionContext actionContext) { if(actionContext.ActionDescriptor.GetCustomAttributes<SkipMyActionFilterAttribute>().Any()) { return; } //Do something } } 的解决方案,其中我们使用tidyverse指定所有summarise_at并将它们与PC[0-9]关联。与A相同的过程,然后简单地合并,即

B

给出,

library(tidyverse)

df %>% 
 group_by(loc, seas) %>% 
 summarise_at(vars(starts_with('PC')), funs(cor(., A))) %>% 
 left_join(., df %>% 
                 group_by(loc, seas) %>% 
                 summarise_at(vars(starts_with('PC')), funs(cor(., B))), 
          by = c('loc', 'seas'), suffix = c('.A', '.B'))

答案 2 :(得分:3)

我们可以在split中进行corbase R

lapply(split(df[1:5], df[-(1:5)]), cor)
#$A.S
#            PC1        PC2        PC3          A           B
#PC1  1.00000000 -0.3941583  0.1872622  0.4576316 -0.00925106
#PC2 -0.39415826  1.0000000 -0.6797708  0.3522161  0.20916667
#PC3  0.18726218 -0.6797708  1.0000000 -0.2003091  0.37414025
#A    0.45763159  0.3522161 -0.2003091  1.0000000  0.57292305
#B   -0.00925106  0.2091667  0.3741403  0.5729230  1.00000000

#$B.S
#            PC1         PC2         PC3           A          B
#PC1  1.00000000 -0.52651449  0.07120701 -0.01779813 -0.7432814
#PC2 -0.52651449  1.00000000 -0.05448583 -0.35011878  0.4632416
#PC3  0.07120701 -0.05448583  1.00000000  0.80342399  0.4580262
#A   -0.01779813 -0.35011878  0.80342399  1.00000000  0.5558740
#B   -0.74328144  0.46324158  0.45802622  0.55587404  1.0000000

#$A.W
#           PC1         PC2        PC3          A           B
#PC1  1.0000000 -0.79784422  0.0932317  0.7483545  0.49639477
#PC2 -0.7978442  1.00000000 -0.3526315 -0.3994917 -0.05233889
#PC3  0.0932317 -0.35263151  1.0000000 -0.5902400  0.36066898
#A    0.7483545 -0.39949171 -0.5902400  1.0000000  0.18081316
#B    0.4963948 -0.05233889  0.3606690  0.1808132  1.00000000

#$B.W
#           PC1        PC2        PC3          A          B
#PC1  1.0000000  0.3441459  0.1135686 -0.4502518 -0.6672104
#PC2  0.3441459  1.0000000 -0.8447551 -0.9899521 -0.8098906
#PC3  0.1135686 -0.8447551  1.0000000  0.7606430  0.3738706
#A   -0.4502518 -0.9899521  0.7606430  1.0000000  0.8832408
#B   -0.6672104 -0.8098906  0.3738706  0.8832408  1.0000000

或使用tidyverse

library(tidyverse)
df %>% 
    group_by_at(6:7) %>% 
    nest %>% 
    mutate(data = map(data, cor))