当具有不同的字符串长度时,R将字符串拆分为多列,dplyr
R split a character string into multiple columns when have different string lengths, dplyr
我有动物追踪数据,随着时间的推移遇到每只动物,并且每次遇到的性别都被记录下来。共有三种类型的遭遇(类型 1、类型 2 和类型 3)。每行代表一种动物,每次相遇都被归类为 M(雄性)或 F(雌性)。类型中的每个字符代表一次遭遇(例如 MMMM 是一种动物,出现四次,每次都记录为男性)。
示例数据:
animal.ID type1 type2 type3
1 MMMMMMM M M
2 MFMM M M
3 FFM F F
4 FFFFFFFFF F F
5 MM M M
我想知道每只动物的性别(雄性或雌性)记录是否一致。
我想制作这样的东西,其中一列表示性别是否始终如一地记录(1)或不一致(0)。
animal.ID type1 type2 type3 consistent
1 MMMMMMM M M 1
2 MFMM M M 0
3 FFM F F 0
4 FFFFFFFFF F F 1
5 MM M M 1
我可以使用 if_else 获取 type2 和 type3 数据的 'consistent' 列:
df %>%
mutate(consistent = if_else(type2 == type3), 1, 0))
但是,我不能包含 type1 数据,因为它在每个字符串中有多个字符,而且每个字符串中的字符数不同。
一种方法是使用 str_split 将 type1 拆分为多列,但是,鉴于每个字符串中的字符数不同,我不知道该怎么做。
一种方法可能是使用 strsplit
和 unlist
,检查所有字符是否等于 type2
(除了检查 type2
是否等于 type3
).
df %>%
rowwise() %>%
mutate(consistent = ifelse(type2 == type3 & all(unlist(strsplit(type1, "")) == type2), 1, 0))
输出
# A tibble: 5 x 5
animal.ID type1 type2 type3 consistent
<int> <chr> <chr> <chr> <dbl>
1 1 MMMMMMM M M 1
2 2 MFMM M M 0
3 3 FFM F F 0
4 4 FFFFFFFFF F F 1
5 5 MM M M 1
我们可以使用charToRaw
得到type1
的"raw"表示,如果它们都相同则赋值1。
df$consistent <- +(sapply(df$type1, function(x) length(unique(charToRaw(x)))) ==1)
使用dplyr
,我们可以使用与以下相同的逻辑:
library(dplyr)
df %>%
rowwise() %>%
mutate(consistent = +(n_distinct(charToRaw(type1)) == 1))
# animal.ID type1 type2 type3 consistent
# <int> <chr> <chr> <chr> <int>
#1 1 MMMMMMM M M 1
#2 2 MFMM M M 0
#3 3 FFM F F 0
#4 4 FFFFFFFFF F F 1
#5 5 MM M M 1
数据
df <- structure(list(animal.ID = 1:5, type1 = c("MMMMMMM", "MFMM",
"FFM", "FFFFFFFFF", "MM"), type2 = c("M", "M", "F", "F", "M"),
type3 = c("M", "M", "F", "F", "M")), class = "data.frame", row.names = c(NA, -5L))
另一个使用逻辑的解决方案@Ronak Shah
library(tidyverse)
df %>%
unite("all_type", starts_with("type"), sep = "", remove = F) %>%
mutate(consistent = map(strsplit(all_type, ""), ~ +(n_distinct(.x) == 1)))
我有动物追踪数据,随着时间的推移遇到每只动物,并且每次遇到的性别都被记录下来。共有三种类型的遭遇(类型 1、类型 2 和类型 3)。每行代表一种动物,每次相遇都被归类为 M(雄性)或 F(雌性)。类型中的每个字符代表一次遭遇(例如 MMMM 是一种动物,出现四次,每次都记录为男性)。
示例数据:
animal.ID type1 type2 type3
1 MMMMMMM M M
2 MFMM M M
3 FFM F F
4 FFFFFFFFF F F
5 MM M M
我想知道每只动物的性别(雄性或雌性)记录是否一致。
我想制作这样的东西,其中一列表示性别是否始终如一地记录(1)或不一致(0)。
animal.ID type1 type2 type3 consistent
1 MMMMMMM M M 1
2 MFMM M M 0
3 FFM F F 0
4 FFFFFFFFF F F 1
5 MM M M 1
我可以使用 if_else 获取 type2 和 type3 数据的 'consistent' 列:
df %>%
mutate(consistent = if_else(type2 == type3), 1, 0))
但是,我不能包含 type1 数据,因为它在每个字符串中有多个字符,而且每个字符串中的字符数不同。
一种方法是使用 str_split 将 type1 拆分为多列,但是,鉴于每个字符串中的字符数不同,我不知道该怎么做。
一种方法可能是使用 strsplit
和 unlist
,检查所有字符是否等于 type2
(除了检查 type2
是否等于 type3
).
df %>%
rowwise() %>%
mutate(consistent = ifelse(type2 == type3 & all(unlist(strsplit(type1, "")) == type2), 1, 0))
输出
# A tibble: 5 x 5
animal.ID type1 type2 type3 consistent
<int> <chr> <chr> <chr> <dbl>
1 1 MMMMMMM M M 1
2 2 MFMM M M 0
3 3 FFM F F 0
4 4 FFFFFFFFF F F 1
5 5 MM M M 1
我们可以使用charToRaw
得到type1
的"raw"表示,如果它们都相同则赋值1。
df$consistent <- +(sapply(df$type1, function(x) length(unique(charToRaw(x)))) ==1)
使用dplyr
,我们可以使用与以下相同的逻辑:
library(dplyr)
df %>%
rowwise() %>%
mutate(consistent = +(n_distinct(charToRaw(type1)) == 1))
# animal.ID type1 type2 type3 consistent
# <int> <chr> <chr> <chr> <int>
#1 1 MMMMMMM M M 1
#2 2 MFMM M M 0
#3 3 FFM F F 0
#4 4 FFFFFFFFF F F 1
#5 5 MM M M 1
数据
df <- structure(list(animal.ID = 1:5, type1 = c("MMMMMMM", "MFMM",
"FFM", "FFFFFFFFF", "MM"), type2 = c("M", "M", "F", "F", "M"),
type3 = c("M", "M", "F", "F", "M")), class = "data.frame", row.names = c(NA, -5L))
另一个使用逻辑的解决方案@Ronak Shah
library(tidyverse)
df %>%
unite("all_type", starts_with("type"), sep = "", remove = F) %>%
mutate(consistent = map(strsplit(all_type, ""), ~ +(n_distinct(.x) == 1)))