r - 为整个数据集和计数在 R 中自动化 "for loop"

标签 r dataframe loops for-loop purrr

我正在做一个分析,我在 R 方面没有那么先进。我被困在这个阶段。非常感谢您在这方面的热心帮助。

在示例数据集(data1)中,我有 7 列(a、b、c、d、e、f、g)。前 3 列(a、b、c)来自一个组,其他 4 列(d、e、f、g)来自不同的组。

在我的 data1 中,我为 2 个组中的每个组合对应用了一个 TRUE/FALSE (1/0) 输出公式 [a,每列 d、e、f、 g (ad, ae, af, ag); b 每列 (bd, be, bf, bg); c 与每一列 (cd, ce, cf, cg)]。在我的示例中,我尝试为 c 和 d 列 (cd) 执行此操作。但是,它没有向我显示正确的输出。在我想要的输出中,第二个输出应该是 1 (TRUE)。而且,我不知道如何自动化整个数据集的循环。

**注由于 parent line 的任何值都可以满足条件,所以我在循环中使用 | 来获取结果。但是,我不确定这是否是正确或有效的方式。

a <- c(0, 0.501, 0.501, 0, 0.57, 20)
b <- c(0.108, 0.96, 0.110, 0.10, 4, 2)
c <- c(0.110, 1, 0.118, 0.107, 0.34, 0.019)
d <- c(0.115, 0.113, 0.98, 0.1, 13, 2)
e <- c(1, 3.113, 0.98, 0.560, 0.15, 1)
f <- c(2.45, 4.16, 0.045, 0.9, 0.12, 70)
g <- c(2, 0.6, 3, 7, 0.12, 29)

data1 <- data.frame(a, b, c, d, e, f, g)
rownames(data1) <- c(("Man2"), paste0('Man', 4:8))
data1
#>           a     b     c      d     e      f     g
#> Man2  0.000 0.108 0.110  0.115 1.000  2.450  2.00
#> Man4  0.501 0.960 1.000  0.113 3.113  4.160  0.60
#> Man5  0.501 0.110 0.118  0.980 0.980  0.045  3.00
#> Man6  0.000 0.100 0.107  0.100 0.560  0.900  7.00
#> Man7  0.570 4.000 0.340 13.000 0.150  0.120  0.12
#> Man8 20.000 2.000 0.019  2.000 1.000 70.000 29.00
r <- c(1:6) #number of rows
c <- c(1:7)  #number of cols
f <- c(1:3) #first group (a, b, c)
s <- c(4:7)  #second group (d, e, f, g)

for (i in r) {
    if ((data1[i,3] >= 0.5 & data1[i,4] >= data1[i, 3]*2) | (data1[i,4] >= 0.5 & data1[i,3] >= data1[i,4]*2)) {
      print(1L)
    } else if ((data1[i,3] < 0.5  & data1[i,4] >= 1.0) | (data1[i,4] < 0.5 & data1[1,3] >= 1.0)) {
      print(1L)
    } else {
      print(0L)
    }
  }
#> [1] 0
#> [1] 0
#> [1] 0
#> [1] 0
#> [1] 1
#> [1] 1

reprex package 于 2021-06-21 创建(v2.0.0)

对于每个组合,

  • 如果任一列的值为>= 0.5,则另一列的值为>= 2 倍,
  • 如果任一列的值低于 0.5,则另一列中的值需要为每行 >= 1

我寻找这样的输出 df:

ad <- c(0L, 0L, 0L, 0L, 1L, 1L)
ae <- c(1L, 1L, 0L, 0L, 0L, 1L)
af <- c(1L, 1L, 0L, 0L, 0L, 1L)
ag <- c(1L, 0L, 1L, 1L, 0L, 0L)
bd <- c(0L, 0L, 0L, 0L, 1L, 0L)
be <- c(1L, 1L, 0L, 0L, 1L, 1L)
bf <- c(1L, 1L, 0L, 0L, 1L, 1L)
bg <- c(1L, 0L, 1L, 1L, 1L, 1L)
cd <- c(0L, 1L, 0L, 0L, 1L, 1L)
ce <- c(1L, 1L, 0L, 0L, 0L, 1L)
cf <- c(1L, 1L, 0L, 0L, 0L, 1L)
cg <- c(1L, 1L, 1L, 1L, 0L, 1L)
df <- data.frame(ad, ae, af, ag, bd, be, bf, bg, cd, ce, cf, cg)
rownames(df) <- c(("Man2"), paste0('Man', 4:8))
df
#>      ad ae af ag bd be bf bg cd ce cf cg
#> Man2  0  1  1  1  0  1  1  1  0  1  1  1
#> Man4  0  1  1  0  0  1  1  0  1  1  1  1
#> Man5  0  0  0  1  0  0  0  1  0  0  0  1
#> Man6  0  0  0  1  0  0  0  1  0  0  0  1
#> Man7  1  0  0  0  1  1  1  1  1  0  0  0
#> Man8  1  1  1  0  0  1  1  1  1  1  1  1

reprex package 于 2021-06-21 创建(v2.0.0)

我在组合对中也有两组。我想计算一组 c(ad, ae, bg, be, bf, cd) 和另一组 c(af, ag, bd, ce, cf, cg) 为每一行。将 1/0 输出保存在像 df 这样的新数据帧中还是只将“1s”的计数放在两个新列中(如 df2 )?工作数据集是一个巨大的。所以,内存和高效的方式是这里的问题。 我想要的输出是这样的 [counting 1s for the first combination group c(ad, ae, bg, be, bf, cd) 并且还计算 1s for the second combination group c( af, ag, bd, ce, cf, cg) 每行]:

ad <- c(0L, 0L, 0L, 0L, 1L, 1L)
ae <- c(1L, 1L, 0L, 0L, 0L, 1L)
af <- c(1L, 1L, 0L, 0L, 0L, 1L)
ag <- c(1L, 0L, 1L, 1L, 0L, 0L)
bd <- c(0L, 0L, 0L, 0L, 1L, 0L)
be <- c(1L, 1L, 0L, 0L, 1L, 1L)
bf <- c(1L, 1L, 0L, 0L, 1L, 1L)
bg <- c(1L, 0L, 1L, 1L, 1L, 1L)
cd <- c(0L, 1L, 0L, 0L, 1L, 1L)
ce <- c(1L, 1L, 0L, 0L, 0L, 1L)
cf <- c(1L, 1L, 0L, 0L, 0L, 1L)
cg <- c(1L, 0L, 1L, 1L, 0L, 1L)
#first_group <- c(ad, ae, bg, be, bf, cd)
#second_group <- c(af, ag, bd, ce, cf, cg) 
first_combi <- c(4, 4, 1, 1, 5, 5)
second_combi <- c(5, 3, 2, 2, 1, 4)
df2 <- data.frame(ad, ae, af, ag, bd, be, bf, bg, cd, ce, cf, cg, first_combi, second_combi)
rownames(df2) <- c(("Man2"), paste0('Man', 4:8))
df2
#>      ad ae af ag bd be bf bg cd ce cf cg first_combi second_combi
#> Man2  0  1  1  1  0  1  1  1  0  1  1  1           4            5
#> Man4  0  1  1  0  0  1  1  0  1  1  1  0           4            3
#> Man5  0  0  0  1  0  0  0  1  0  0  0  1           1            2
#> Man6  0  0  0  1  0  0  0  1  0  0  0  1           1            2
#> Man7  1  0  0  0  1  1  1  1  1  0  0  0           5            1
#> Man8  1  1  1  0  0  1  1  1  1  1  1  1           5            4

reprex package 于 2021-06-21 创建(v2.0.0)

所以,我需要两个建议:

  1. 如何自动化整个数据集的循环
  2. 如何存储两个组合组的 1/0 (TRUE/FALSE) 并为组计数“1”。

请帮我解决数据集的这两个问题。

最佳答案

tidyverse 策略。对于第二部分,我假设您想要矩阵形式的 colsum。

  • 我已将您的列名分为两组,分别为 grp_1grp_2
  • exapnd.grid 将生成两个名称组的所有组合
  • 接下来我们将把它作为第一个参数传递给 pmap_dfc
  • 对于功能部分,我有
    • 将逻辑值存储到临时变量 x 中。在存储之前,我已经用 + 包装了整个条件,它将逻辑值转换为数字
    • 接下来,我使用 paste0
    • 根据组组合设置了这个 x 的名称
  • 由于使用了pmap_dfc,结果会自动绑定(bind)到列中
  • 最后的代码恢复了行名

对于我使用的第二部分 -

  • 外部函数,结合
  • colSums.

使用 colSums 将直接根据列名而不是矩阵为您提供结果

library(tidyverse)

#optimised solution #for the loop part
gr_1 <- c('a', 'b', 'c')
gr_2 <- c('d', 'e', 'f', 'g')

expand.grid(gr_1, gr_2, stringsAsFactors = F) %>%
  pmap_dfc(~ {x <- +((data1[[..1]] >= 0.5 & data1[[..2]] >  2 * data1[[..1]]) |
                       (data1[[..2]] >= 0.5 & data1[[..1]] >  2 * data1[[..2]]) | 
                       (data1[[..2]] < 0.5 &  data1[[..1]] >= 1) |
                       (data1[[..1]] < 0.5 &  data1[[..2]] >= 1)); setNames(list(x), paste0(..1, ..2))} ) %>%
  as.data.frame() %>%
  `rownames<-`(rownames(data1)) -> res

res
#>      ad bd cd ae be ce af bf cf ag bg cg
#> Man2  0  0  0  1  1  1  1  1  1  1  1  1
#> Man4  0  0  1  1  1  1  1  1  1  0  0  0
#> Man5  0  0  0  0  0  0  0  0  0  1  1  1
#> Man6  0  0  0  0  0  0  0  0  0  1  1  1
#> Man7  1  1  1  0  1  0  0  1  0  0  1  0
#> Man8  1  0  1  1  0  1  1  1  1  0  1  1

第二部分

#second part
out_gr1 <- c('ad', 'ae', 'bg', 'be', 'bf', 'cd')

split.default(res,  c('Gr1', 'Gr2')[1 + !(names(res) %in% out_gr1)]) %>%
  sapply(rowSums)
  
     Gr1 Gr2
Man2   4   5
Man4   4   3
Man5   1   2
Man6   1   2
Man7   5   1
Man8   5   4

在一个管道中完成

gr_1 <- c('a', 'b', 'c')
gr_2 <- c('d', 'e', 'f', 'g')
out_gr1 <- c('ad', 'ae', 'bg', 'be', 'bf', 'cd')

expand.grid(gr_1, gr_2, stringsAsFactors = F) %>%
  pmap_dfc(~ {x <- +((data1[[..1]] >= 0.5 & data1[[..2]] >  2 * data1[[..1]]) |
                       (data1[[..2]] >= 0.5 & data1[[..1]] >  2 * data1[[..2]]) | 
                       (data1[[..2]] < 0.5 &  data1[[..1]] >= 1) |
                       (data1[[..1]] < 0.5 &  data1[[..2]] >= 1)); setNames(list(x), paste0(..1, ..2))} ) %>%
  as.data.frame() %>%
  `rownames<-`(rownames(data1)) %>% cbind(split.default(., c('First_combi', 'Second_combi')[1 + !(names(.) %in% out_gr1)]) %>%
  sapply(rowSums))

     ad bd cd ae be ce af bf cf ag bg cg First_combi Second_combi
Man2  0  0  0  1  1  1  1  1  1  1  1  1           4            5
Man4  0  0  1  1  1  1  1  1  1  0  0  0           4            3
Man5  0  0  0  0  0  0  0  0  0  1  1  1           1            2
Man6  0  0  0  0  0  0  0  0  0  1  1  1           1            2
Man7  1  1  1  0  1  0  0  1  0  0  1  0           5            1
Man8  1  0  1  1  0  1  1  1  1  0  1  1           5            4

关于r - 为整个数据集和计数在 R 中自动化 "for loop",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68062589/

相关文章:

java - 如何在二维数组中的变量行中循环我的代码?

r - 在 kableExtra() 中格式化标题

r - 保留 geom_rect() 中的顺序

scala - 根据包含列表元素的列值创建 bool 标志

r - 从数据框错误:target of assignment expands to non-language object删除列

python - 按列计算两个 DataFrame 的相关性

c++ - If/else 循环 : C++ Program: Won't display final prompt/final loop

algorithm - "Flip"仅使用 +1/-1 而不使用 if/else 的简单循环的输出

r - 在 ggplot2 分面标题下划线

R - 查找 data.table 中第一个非零元素的索引