如何根据 R 中其他列的多个条件创建多个新列?
How to create multiple new columns based on multiple conditions of other columns in R?
我想弄清楚如何根据其他列创建新列并将另一列的值作为观察值插入新创建的列中。
不确定如何用语言清楚地解释这一点,所以我将展示一个例子。
基本上我的数据是这样的:
code
spec
grid
month
day
depth
number
01
31
1
6
17
5
1
01
33
1
6
17
5
2
01
45
1
6
17
10
15
02
45
12
6
17
10
34
02
45
12
7
19
15
1
03
31
15
8
27
15
30
03
33
16
9
13
20
34
03
31
18
10
17
25
100
我的数据集有 2,514 行。
'spec'栏是物种代码。我想创建新的列,其中包含实际的物种名称(对于每个物种代码)及其各自的编号作为观察值(行)。
例如(simplified/mock 出于隐私目的的数据)。
让我们说物种代码:31 ==蚊子,33 ==狮子,45 ==鱼......等等。
我希望我的数据像这样结束:
code
mosquito
lion
fish
grid
month
day
depth
01
1
0
0
1
6
17
5
01
0
2
0
1
6
17
5
01
0
0
15
1
6
17
10
02
0
0
34
12
6
17
10
02
0
0
1
12
7
19
15
03
30
0
0
15
8
27
15
03
0
34
0
16
9
13
20
03
100
0
0
18
10
17
25
- 包含每个独特物种代码的物种名称的新列(我的数据中可能有大约 15 个物种,因此应该有 ~15 个新列)
- 每个物种都应该有其各自的 'number',如果物种没有被计算在内,它应该有一个 '0'
- 设置完成后,'number' 和 'spec' 列可以删除。
*当然,数据需要与其各自的日期、月份、代码、网格等对齐,因此没有其他内容是 changed/modified 来自原始数据
我在网上看了几个小时,但一直没能找到明确的答案...
我找到了更简单的解决方案,但无法满足我的问题。
我试过 case_when、if_else 和 sapply,但似乎无法正常工作。
我希望这个问题很清楚。很高兴进一步澄清。
有什么建议么?
谢谢!
你可以使用
library(dplyr)
library(tidyr)
df1 %>%
left_join(df2, by = "spec") %>%
pivot_wider(values_from = "number", values_fill = 0) %>%
select(code, mosquito, lion, fish, grid, month, day, depth)
这个returns
# A tibble: 8 x 8
code mosquito lion fish grid month day depth
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 01 1 0 0 1 6 17 5
2 01 0 2 0 1 6 17 5
3 01 0 0 15 1 6 17 10
4 02 0 0 34 12 6 17 10
5 02 0 0 1 12 7 19 15
6 03 30 0 0 15 8 27 15
7 03 0 34 0 16 9 13 20
8 03 100 0 0 18 10 17 25
我使用了两个数据框:你显示的数据
structure(list(code = c("01", "01", "01", "02", "02", "03", "03",
"03"), spec = c(31, 33, 45, 45, 45, 31, 33, 31), grid = c(1,
1, 1, 12, 12, 15, 16, 18), month = c(6, 6, 6, 6, 7, 8, 9, 10),
day = c(17, 17, 17, 17, 19, 27, 13, 17), depth = c(5, 5,
10, 10, 15, 15, 20, 25), number = c(1, 2, 15, 34, 1, 30,
34, 100)), class = c("spec_tbl_df", "tbl_df", "tbl", "data.frame"
), row.names = c(NA, -8L), spec = structure(list(cols = list(
code = structure(list(), class = c("collector_character",
"collector")), spec = structure(list(), class = c("collector_double",
"collector")), grid = structure(list(), class = c("collector_double",
"collector")), month = structure(list(), class = c("collector_double",
"collector")), day = structure(list(), class = c("collector_double",
"collector")), depth = structure(list(), class = c("collector_double",
"collector")), number = structure(list(), class = c("collector_double",
"collector"))), default = structure(list(), class = c("collector_guess",
"collector")), skip = 1L), class = "col_spec"))
和一个data.frame用于将spec
转换为真正的物种名称:
structure(list(spec = c(31, 33, 45), name = c("mosquito", "lion",
"fish")), class = c("spec_tbl_df", "tbl_df", "tbl", "data.frame"
), row.names = c(NA, -3L), spec = structure(list(cols = list(
spec = structure(list(), class = c("collector_double", "collector"
)), name = structure(list(), class = c("collector_character",
"collector"))), default = structure(list(), class = c("collector_guess",
"collector")), skip = 1L), class = "col_spec"))
你可以这样做:
library(tidyverse)
df %>%
mutate(spec = case_when(
spec == 31 ~ 'mosquito',
spec == 33 ~ 'lion',
spec == 45 ~ 'fish',
TRUE ~ NA_character_),
id = row_number()) %>%
pivot_wider(names_from = spec, values_from = number) %>%
mutate(across(everything(), ~ replace_na(.x, 0)))
#> # A tibble: 8 x 9
#> code grid month day depth id mosquito lion fish
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 1 1 6 17 5 1 1 0 0
#> 2 1 1 6 17 5 2 0 2 0
#> 3 1 1 6 17 10 3 0 0 15
#> 4 2 12 6 17 10 4 0 0 34
#> 5 2 12 7 19 15 5 0 0 1
#> 6 3 15 8 27 15 6 30 0 0
#> 7 3 16 9 13 20 7 0 34 0
#> 8 3 18 10 17 25 8 100 0 0
请注意,您需要将您的其他物种映射到 case_when
中的 spec
编号
由 reprex package (v2.0.1)
于 2022-04-10 创建
来自问题的可重现格式的数据:
``` r
df <- structure(list(code = c(1L, 1L, 1L, 2L, 2L, 3L, 3L, 3L), spec = c(31L,
33L, 45L, 45L, 45L, 31L, 33L, 31L), grid = c(1L, 1L, 1L, 12L,
12L, 15L, 16L, 18L), month = c(6L, 6L, 6L, 6L, 7L, 8L, 9L, 10L
), day = c(17L, 17L, 17L, 17L, 19L, 27L, 13L, 17L), depth = c(5L,
5L, 10L, 10L, 15L, 15L, 20L, 25L), number = c(1L, 2L, 15L, 34L,
1L, 30L, 34L, 100L)), class = "data.frame", row.names = c(NA,
-8L))
df
#> code spec grid month day depth number
#> 1 1 31 1 6 17 5 1
#> 2 1 33 1 6 17 5 2
#> 3 1 45 1 6 17 10 15
#> 4 2 45 12 6 17 10 34
#> 5 2 45 12 7 19 15 1
#> 6 3 31 15 8 27 15 30
#> 7 3 33 16 9 13 20 34
#> 8 3 31 18 10 17 25 100
我想弄清楚如何根据其他列创建新列并将另一列的值作为观察值插入新创建的列中。 不确定如何用语言清楚地解释这一点,所以我将展示一个例子。
基本上我的数据是这样的:
code | spec | grid | month | day | depth | number |
---|---|---|---|---|---|---|
01 | 31 | 1 | 6 | 17 | 5 | 1 |
01 | 33 | 1 | 6 | 17 | 5 | 2 |
01 | 45 | 1 | 6 | 17 | 10 | 15 |
02 | 45 | 12 | 6 | 17 | 10 | 34 |
02 | 45 | 12 | 7 | 19 | 15 | 1 |
03 | 31 | 15 | 8 | 27 | 15 | 30 |
03 | 33 | 16 | 9 | 13 | 20 | 34 |
03 | 31 | 18 | 10 | 17 | 25 | 100 |
我的数据集有 2,514 行。
'spec'栏是物种代码。我想创建新的列,其中包含实际的物种名称(对于每个物种代码)及其各自的编号作为观察值(行)。
例如(simplified/mock 出于隐私目的的数据)。 让我们说物种代码:31 ==蚊子,33 ==狮子,45 ==鱼......等等。 我希望我的数据像这样结束:
code | mosquito | lion | fish | grid | month | day | depth |
---|---|---|---|---|---|---|---|
01 | 1 | 0 | 0 | 1 | 6 | 17 | 5 |
01 | 0 | 2 | 0 | 1 | 6 | 17 | 5 |
01 | 0 | 0 | 15 | 1 | 6 | 17 | 10 |
02 | 0 | 0 | 34 | 12 | 6 | 17 | 10 |
02 | 0 | 0 | 1 | 12 | 7 | 19 | 15 |
03 | 30 | 0 | 0 | 15 | 8 | 27 | 15 |
03 | 0 | 34 | 0 | 16 | 9 | 13 | 20 |
03 | 100 | 0 | 0 | 18 | 10 | 17 | 25 |
- 包含每个独特物种代码的物种名称的新列(我的数据中可能有大约 15 个物种,因此应该有 ~15 个新列)
- 每个物种都应该有其各自的 'number',如果物种没有被计算在内,它应该有一个 '0'
- 设置完成后,'number' 和 'spec' 列可以删除。 *当然,数据需要与其各自的日期、月份、代码、网格等对齐,因此没有其他内容是 changed/modified 来自原始数据
我在网上看了几个小时,但一直没能找到明确的答案... 我找到了更简单的解决方案,但无法满足我的问题。
我试过 case_when、if_else 和 sapply,但似乎无法正常工作。 我希望这个问题很清楚。很高兴进一步澄清。 有什么建议么? 谢谢!
你可以使用
library(dplyr)
library(tidyr)
df1 %>%
left_join(df2, by = "spec") %>%
pivot_wider(values_from = "number", values_fill = 0) %>%
select(code, mosquito, lion, fish, grid, month, day, depth)
这个returns
# A tibble: 8 x 8
code mosquito lion fish grid month day depth
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 01 1 0 0 1 6 17 5
2 01 0 2 0 1 6 17 5
3 01 0 0 15 1 6 17 10
4 02 0 0 34 12 6 17 10
5 02 0 0 1 12 7 19 15
6 03 30 0 0 15 8 27 15
7 03 0 34 0 16 9 13 20
8 03 100 0 0 18 10 17 25
我使用了两个数据框:你显示的数据
structure(list(code = c("01", "01", "01", "02", "02", "03", "03",
"03"), spec = c(31, 33, 45, 45, 45, 31, 33, 31), grid = c(1,
1, 1, 12, 12, 15, 16, 18), month = c(6, 6, 6, 6, 7, 8, 9, 10),
day = c(17, 17, 17, 17, 19, 27, 13, 17), depth = c(5, 5,
10, 10, 15, 15, 20, 25), number = c(1, 2, 15, 34, 1, 30,
34, 100)), class = c("spec_tbl_df", "tbl_df", "tbl", "data.frame"
), row.names = c(NA, -8L), spec = structure(list(cols = list(
code = structure(list(), class = c("collector_character",
"collector")), spec = structure(list(), class = c("collector_double",
"collector")), grid = structure(list(), class = c("collector_double",
"collector")), month = structure(list(), class = c("collector_double",
"collector")), day = structure(list(), class = c("collector_double",
"collector")), depth = structure(list(), class = c("collector_double",
"collector")), number = structure(list(), class = c("collector_double",
"collector"))), default = structure(list(), class = c("collector_guess",
"collector")), skip = 1L), class = "col_spec"))
和一个data.frame用于将spec
转换为真正的物种名称:
structure(list(spec = c(31, 33, 45), name = c("mosquito", "lion",
"fish")), class = c("spec_tbl_df", "tbl_df", "tbl", "data.frame"
), row.names = c(NA, -3L), spec = structure(list(cols = list(
spec = structure(list(), class = c("collector_double", "collector"
)), name = structure(list(), class = c("collector_character",
"collector"))), default = structure(list(), class = c("collector_guess",
"collector")), skip = 1L), class = "col_spec"))
你可以这样做:
library(tidyverse)
df %>%
mutate(spec = case_when(
spec == 31 ~ 'mosquito',
spec == 33 ~ 'lion',
spec == 45 ~ 'fish',
TRUE ~ NA_character_),
id = row_number()) %>%
pivot_wider(names_from = spec, values_from = number) %>%
mutate(across(everything(), ~ replace_na(.x, 0)))
#> # A tibble: 8 x 9
#> code grid month day depth id mosquito lion fish
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 1 1 6 17 5 1 1 0 0
#> 2 1 1 6 17 5 2 0 2 0
#> 3 1 1 6 17 10 3 0 0 15
#> 4 2 12 6 17 10 4 0 0 34
#> 5 2 12 7 19 15 5 0 0 1
#> 6 3 15 8 27 15 6 30 0 0
#> 7 3 16 9 13 20 7 0 34 0
#> 8 3 18 10 17 25 8 100 0 0
请注意,您需要将您的其他物种映射到 case_when
spec
编号
由 reprex package (v2.0.1)
于 2022-04-10 创建来自问题的可重现格式的数据:
``` r
df <- structure(list(code = c(1L, 1L, 1L, 2L, 2L, 3L, 3L, 3L), spec = c(31L,
33L, 45L, 45L, 45L, 31L, 33L, 31L), grid = c(1L, 1L, 1L, 12L,
12L, 15L, 16L, 18L), month = c(6L, 6L, 6L, 6L, 7L, 8L, 9L, 10L
), day = c(17L, 17L, 17L, 17L, 19L, 27L, 13L, 17L), depth = c(5L,
5L, 10L, 10L, 15L, 15L, 20L, 25L), number = c(1L, 2L, 15L, 34L,
1L, 30L, 34L, 100L)), class = "data.frame", row.names = c(NA,
-8L))
df
#> code spec grid month day depth number
#> 1 1 31 1 6 17 5 1
#> 2 1 33 1 6 17 5 2
#> 3 1 45 1 6 17 10 15
#> 4 2 45 12 6 17 10 34
#> 5 2 45 12 7 19 15 1
#> 6 3 31 15 8 27 15 30
#> 7 3 33 16 9 13 20 34
#> 8 3 31 18 10 17 25 100