使用 tidyverse 替换两个 for 循环(dplyr 和 purrr)
Replace two for loops using tidyverse (dplyr and purrr)
我有一个小问题
raw.tb
#> # A tibble: 10 x 4
#> geno ind X Y
#> * <fctr> <fctr> <int> <int>
#> 1 san1w16 A1 467 383
#> 2 san1w16 A1 465 378
#> 3 san1w16 B1 464 378
#> 4 san1w16 B1 464 377
#> 5 san2w16 A1 464 376
#> 6 san2w16 A1 464 375
#> 7 san2w16 B1 463 375
#> 8 san2w16 B1 463 374
#> 9 san3w16 A1 463 373
#> 10 san3w16 A1 463 372
我想用 tidyverse 替换两个 for
循环的用法。我正在使用一个需要 2x2 矩阵的函数(它可以是任何函数 - 在这种特定情况下它是 momocs::coo_rotate)。
我想做的事情可以这样写在 base R 中:
for(g in unique(raw.tb$geno)){
for(i in unique(raw.tb[raw.tb$geno == g,]$ind){
raw.tb[raw.tb$geno == g & raw.tb$ind == i,c(3,4)] = some.function.for.a.matrix(raw.tb[raw.tb$geno == g & raw.tb$ind == i,c(3,4)])
}
}
我猜这可以使用 tidyverse 来完成,但是我看过 group_by()
与 do()
以及 nest
与 map
一起使用,但我不能让它起作用。
我有点猜测,因为我不清楚你到底想做什么。
raw.tb <- structure(list(geno = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L), .Label = "san1w16", class = "factor"), ind = structure(c(1L,
1L, 2L, 2L, 3L, 3L, 4L, 4L, 5L, 1L), .Label = c("A1", "B1", "C1",
"D1", "E1"), class = "factor"), X = c(467L, 465L, 464L, 464L,
464L, 464L, 463L, 463L, 463L, 463L), Y = c(383L, 378L, 378L,
377L, 376L, 375L, 375L, 374L, 373L, 372L)), .Names = c("geno",
"ind", "X", "Y"), row.names = c("1", "2", "3", "4", "5", "6",
"7", "8", "9", "10"), class = c("tbl_df", "tbl", "data.frame"
)) %>% as_tibble(); raw.tb
#> # A tibble: 10 x 4
#> geno ind X Y
#> * <fctr> <fctr> <int> <int>
#> 1 san1w16 A1 467 383
#> 2 san1w16 A1 465 378
#> 3 san1w16 B1 464 378
#> 4 san1w16 B1 464 377
#> 5 san1w16 C1 464 376
#> 6 san1w16 C1 464 375
#> 7 san1w16 D1 463 375
#> 8 san1w16 D1 463 374
#> 9 san1w16 E1 463 373
#> 10 san1w16 A1 463 372
像这样,
raw.tb %>% group_by(geno) %>% gather(XY, Value, -geno, -ind) %>% arrange(geno, ind)
#> # A tibble: 20 x 4
#> # Groups: geno [1]
#> geno ind XY Value
#> <fctr> <fctr> <chr> <int>
#> 1 san1w16 A1 X 467
#> 2 san1w16 A1 X 465
#> 3 san1w16 A1 X 463
#> 4 san1w16 A1 Y 383
#> 5 san1w16 A1 Y 378
#> 6 san1w16 A1 Y 372
#> 7 san1w16 B1 X 464
#> 8 san1w16 B1 X 464
#> 9 san1w16 B1 Y 378
#> 10 san1w16 B1 Y 377
#> 11 san1w16 C1 X 464
#> 12 san1w16 C1 X 464
#> 13 san1w16 C1 Y 376
#> 14 san1w16 C1 Y 375
#> 15 san1w16 D1 X 463
#> 16 san1w16 D1 X 463
#> 17 san1w16 D1 Y 375
#> 18 san1w16 D1 Y 374
#> 19 san1w16 E1 X 463
#> 20 san1w16 E1 Y 373
从那里您几乎可以应用任何功能。这里有一些 summarise
由 akrun
建议
raw.tb %>% group_by(geno) %>% gather(XY, Value, -geno, -ind) %>%
arrange(geno, ind) %>% group_by(ind, geno, XY) %>%
summarise(Value = mean(Value))
#> # A tibble: 10 x 4
#> # Groups: ind, geno [?]
#> ind geno XY Value
#> <fctr> <fctr> <chr> <dbl>
#> 1 A1 san1w16 X 465.0000
#> 2 A1 san1w16 Y 377.6667
#> 3 B1 san1w16 X 464.0000
#> 4 B1 san1w16 Y 377.5000
#> 5 C1 san1w16 X 464.0000
#> 6 C1 san1w16 Y 375.5000
#> 7 D1 san1w16 X 463.0000
#> 8 D1 san1w16 Y 374.5000
#> 9 E1 san1w16 X 463.0000
#> 10 E1 san1w16 Y 373.0000
或者
raw.tb %>% group_by(geno) %>% gather(XY, Value, -geno, -ind) %>%
arrange(geno, ind) %>% group_by(ind, geno) %>%
summarise(Value = mean(Value))
#> # A tibble: 5 x 3
#> # Groups: ind [?]
#> ind geno Value
#> <fctr> <fctr> <dbl>
#> 1 A1 san1w16 421.3333
#> 2 B1 san1w16 420.7500
#> 3 C1 san1w16 419.7500
#> 4 D1 san1w16 418.7500
#> 5 E1 san1w16 418.0000
我找到了。希望我的回答能让事情更清楚。我向@EricFail 道歉,因为我没有让这个更清楚
基本上我写了一个函数,给定一个 x,y 坐标矩阵,使用第一个和最后一个点作为基线旋转坐标。我没有详细说明该功能,因为它很长而且不是这里的重点,但基本上,该功能的类型是:
rotate.coord <- function(mat){
for(i in 1:dim(mat)[1]{
x1=(dim(coord.rot)[1])
x2=1
.
.
(theta is computed based on x1 and x2)
.
.
xn=mat[z,1]*cos(theta)+mat[z,2]*sin(theta)
yn=-mat[z,1]*sin(theta)+mat[z,2]*cos(theta)
mat[z,1]=xn
mat[z,2]=yn
}
mat = as_tibble(mat)
return(mat)
}
拥有:
raw.tb
#> # A tibble: 10 x 4
#> geno ind X Y
#> * <fctr> <fctr> <int> <int>
#> 1 san1w16 A1 467 383
#> 2 san1w16 A1 465 378
#> 3 san1w16 B1 464 378
#> 4 san1w16 B1 464 377
#> 5 san2w16 A1 464 376
#> 6 san2w16 A1 464 375
#> 7 san2w16 B1 463 375
#> 8 san2w16 B1 463 374
#> 9 san3w16 A1 463 373
#> 10 san3w16 A1 463 372
我想做
raw.nt <- raw.tb %>%
group_by(geno,ind) %>%
nest()
raw.nt2 <- raw.nt %>%
mutate(rot = map(data,rotate.coo))
这会创建一个新的嵌套小标题,其中每个组的 raw.nt2$rot
是每个 raw.nt$data
组的旋转矩阵
我有一个小问题
raw.tb
#> # A tibble: 10 x 4
#> geno ind X Y
#> * <fctr> <fctr> <int> <int>
#> 1 san1w16 A1 467 383
#> 2 san1w16 A1 465 378
#> 3 san1w16 B1 464 378
#> 4 san1w16 B1 464 377
#> 5 san2w16 A1 464 376
#> 6 san2w16 A1 464 375
#> 7 san2w16 B1 463 375
#> 8 san2w16 B1 463 374
#> 9 san3w16 A1 463 373
#> 10 san3w16 A1 463 372
我想用 tidyverse 替换两个 for
循环的用法。我正在使用一个需要 2x2 矩阵的函数(它可以是任何函数 - 在这种特定情况下它是 momocs::coo_rotate)。
我想做的事情可以这样写在 base R 中:
for(g in unique(raw.tb$geno)){
for(i in unique(raw.tb[raw.tb$geno == g,]$ind){
raw.tb[raw.tb$geno == g & raw.tb$ind == i,c(3,4)] = some.function.for.a.matrix(raw.tb[raw.tb$geno == g & raw.tb$ind == i,c(3,4)])
}
}
我猜这可以使用 tidyverse 来完成,但是我看过 group_by()
与 do()
以及 nest
与 map
一起使用,但我不能让它起作用。
我有点猜测,因为我不清楚你到底想做什么。
raw.tb <- structure(list(geno = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L), .Label = "san1w16", class = "factor"), ind = structure(c(1L,
1L, 2L, 2L, 3L, 3L, 4L, 4L, 5L, 1L), .Label = c("A1", "B1", "C1",
"D1", "E1"), class = "factor"), X = c(467L, 465L, 464L, 464L,
464L, 464L, 463L, 463L, 463L, 463L), Y = c(383L, 378L, 378L,
377L, 376L, 375L, 375L, 374L, 373L, 372L)), .Names = c("geno",
"ind", "X", "Y"), row.names = c("1", "2", "3", "4", "5", "6",
"7", "8", "9", "10"), class = c("tbl_df", "tbl", "data.frame"
)) %>% as_tibble(); raw.tb
#> # A tibble: 10 x 4
#> geno ind X Y
#> * <fctr> <fctr> <int> <int>
#> 1 san1w16 A1 467 383
#> 2 san1w16 A1 465 378
#> 3 san1w16 B1 464 378
#> 4 san1w16 B1 464 377
#> 5 san1w16 C1 464 376
#> 6 san1w16 C1 464 375
#> 7 san1w16 D1 463 375
#> 8 san1w16 D1 463 374
#> 9 san1w16 E1 463 373
#> 10 san1w16 A1 463 372
像这样,
raw.tb %>% group_by(geno) %>% gather(XY, Value, -geno, -ind) %>% arrange(geno, ind)
#> # A tibble: 20 x 4
#> # Groups: geno [1]
#> geno ind XY Value
#> <fctr> <fctr> <chr> <int>
#> 1 san1w16 A1 X 467
#> 2 san1w16 A1 X 465
#> 3 san1w16 A1 X 463
#> 4 san1w16 A1 Y 383
#> 5 san1w16 A1 Y 378
#> 6 san1w16 A1 Y 372
#> 7 san1w16 B1 X 464
#> 8 san1w16 B1 X 464
#> 9 san1w16 B1 Y 378
#> 10 san1w16 B1 Y 377
#> 11 san1w16 C1 X 464
#> 12 san1w16 C1 X 464
#> 13 san1w16 C1 Y 376
#> 14 san1w16 C1 Y 375
#> 15 san1w16 D1 X 463
#> 16 san1w16 D1 X 463
#> 17 san1w16 D1 Y 375
#> 18 san1w16 D1 Y 374
#> 19 san1w16 E1 X 463
#> 20 san1w16 E1 Y 373
从那里您几乎可以应用任何功能。这里有一些 summarise
由 akrun
raw.tb %>% group_by(geno) %>% gather(XY, Value, -geno, -ind) %>%
arrange(geno, ind) %>% group_by(ind, geno, XY) %>%
summarise(Value = mean(Value))
#> # A tibble: 10 x 4
#> # Groups: ind, geno [?]
#> ind geno XY Value
#> <fctr> <fctr> <chr> <dbl>
#> 1 A1 san1w16 X 465.0000
#> 2 A1 san1w16 Y 377.6667
#> 3 B1 san1w16 X 464.0000
#> 4 B1 san1w16 Y 377.5000
#> 5 C1 san1w16 X 464.0000
#> 6 C1 san1w16 Y 375.5000
#> 7 D1 san1w16 X 463.0000
#> 8 D1 san1w16 Y 374.5000
#> 9 E1 san1w16 X 463.0000
#> 10 E1 san1w16 Y 373.0000
或者
raw.tb %>% group_by(geno) %>% gather(XY, Value, -geno, -ind) %>%
arrange(geno, ind) %>% group_by(ind, geno) %>%
summarise(Value = mean(Value))
#> # A tibble: 5 x 3
#> # Groups: ind [?]
#> ind geno Value
#> <fctr> <fctr> <dbl>
#> 1 A1 san1w16 421.3333
#> 2 B1 san1w16 420.7500
#> 3 C1 san1w16 419.7500
#> 4 D1 san1w16 418.7500
#> 5 E1 san1w16 418.0000
我找到了。希望我的回答能让事情更清楚。我向@EricFail 道歉,因为我没有让这个更清楚
基本上我写了一个函数,给定一个 x,y 坐标矩阵,使用第一个和最后一个点作为基线旋转坐标。我没有详细说明该功能,因为它很长而且不是这里的重点,但基本上,该功能的类型是:
rotate.coord <- function(mat){
for(i in 1:dim(mat)[1]{
x1=(dim(coord.rot)[1])
x2=1
.
.
(theta is computed based on x1 and x2)
.
.
xn=mat[z,1]*cos(theta)+mat[z,2]*sin(theta)
yn=-mat[z,1]*sin(theta)+mat[z,2]*cos(theta)
mat[z,1]=xn
mat[z,2]=yn
}
mat = as_tibble(mat)
return(mat)
}
拥有:
raw.tb
#> # A tibble: 10 x 4
#> geno ind X Y
#> * <fctr> <fctr> <int> <int>
#> 1 san1w16 A1 467 383
#> 2 san1w16 A1 465 378
#> 3 san1w16 B1 464 378
#> 4 san1w16 B1 464 377
#> 5 san2w16 A1 464 376
#> 6 san2w16 A1 464 375
#> 7 san2w16 B1 463 375
#> 8 san2w16 B1 463 374
#> 9 san3w16 A1 463 373
#> 10 san3w16 A1 463 372
我想做
raw.nt <- raw.tb %>%
group_by(geno,ind) %>%
nest()
raw.nt2 <- raw.nt %>%
mutate(rot = map(data,rotate.coo))
这会创建一个新的嵌套小标题,其中每个组的 raw.nt2$rot
是每个 raw.nt$data