#r #dplyr
#r #dplyr
Вопрос:
У меня есть следующие данные:
df <- data.frame(a=c(0,0,0,1,1,1),
b=c(1,2,3,1,2,3),
c=c("a","b","c","x","y","z"),
stringsAsFactors = FALSE)
df
#> a b c
#> 1 0 1 a
#> 2 0 2 b
#> 3 0 3 c
#> 4 1 1 x
#> 5 1 2 y
#> 6 1 3 z
Я хотел бы создать 4-й столбец «d», который возвращает значение из «c», где «a» = 0 и b = b, вот так:
#> a b c d
#> 1 0 1 a a
#> 2 0 2 b b
#> 3 0 3 c c
#> 4 1 1 x a
#> 5 1 2 y b
#> 6 1 3 z c
Я пытался:
df %>% mutate(d = c[a==0 amp; b==b])
Но это не работает.
Как я могу создать столбец «d» с помощью dplyr?
Комментарии:
1.
b == b
Это опечатка?2.
b = b
всегда будетTRUE
, поэтому вы можете исключить это условие, если это так. Также вы сказалиb = b amp; a = 0
, но в вашем примере вы все еще предоставляете значения для столбца,d
гдеa != 0
. Можете ли вы объяснить это подробнее?3. Итак, для строки # 4 я хочу вернуть значение из «c», где a== 0 и b ==1 («a»). Для строки # 5 я хочу вернуть значение из «c», где a== 0 и b ==2 («b»). И для строки # 6 я хочу вернуть значение из «c», где a== 0 и b ==3 («c»).
Ответ №1:
dplyr
решение:
df1 <- df[df$a == 0,-1]
inner_join(df, df1, by = "b")
# a b c.x c.y
# 1 0 1 a a
# 2 0 2 b b
# 3 0 3 c c
# 4 1 1 x a
# 5 1 2 y b
# 6 1 3 z c
Комментарии:
1. Базовый вариант R для этого является
merge(df, df[df$a == 0, c("b","c")], by="b")
или с переименованиемmerge(df, transform(df[df$a==0,], d=c)[c("b","d")], by="b")
Ответ №2:
С помощью base R вы можете сделать следующее.
inx <- match(df$b, df$b[df$a == 0])
df$d <- df$c[inx]
df
# a b c d
#1 0 1 a a
#2 0 2 b b
#3 0 3 c c
#4 1 1 x a
#5 1 2 y b
#6 1 3 z c
Ответ №3:
Единственная tidyverse
возможность может быть:
df %>%
mutate(d = ifelse(a == 0, c, NA_character_)) %>%
group_by(b) %>%
fill(d)
a b c d
<dbl> <dbl> <chr> <chr>
1 0 1 a a
2 1 1 x a
3 0 2 b b
4 1 2 y b
5 0 3 c c
6 1 3 z c
Вы также можете упорядочить его:
df %>%
mutate(d = ifelse(a == 0, c, NA_character_)) %>%
group_by(b) %>%
fill(d) %>%
arrange(a, b, c)
a b c d
<dbl> <dbl> <chr> <chr>
1 0 1 a a
2 0 2 b b
3 0 3 c c
4 1 1 x a
5 1 2 y b
6 1 3 z c
Чтобы справиться со сценариями, упомянутыми @divibisan, вы можете сделать:
df %>%
mutate(d = ifelse(a == 0, c, NA_character_)) %>%
group_by(b) %>%
fill(d, .direction = "up") %>%
fill(d, .direction = "down") %>%
arrange(a, b, c)
Комментарии:
1. Умное решение! Одна из проблем заключается в том, что для
fill
правильного поведения строка, отличная от NA (гдеa ==0
), должна быть первой (попробуйте сделать это наdf2 <- df[6:1,]
).2. Спасибо — но по какой-то причине вывод столбца d является числовым, где a = 1, b = 2 и c = 3. Есть идеи?
3. @Rez99 Потому что столбец
c
на самом деле является фактором, а не символом. Вы можете исправить это с помощьюas.character
или использоватьstringsAsFactor=F
аргумент при создании фрейма данных4. @divibisan обновил сообщение, спасибо, что заметили это 🙂