R:如果列包含重复的给定组,则创建虚拟

时间:2018-06-14 20:38:03

标签: r dataframe

我想创建一个虚拟变量,如果在两个或多个不同年龄组中观察到个体,则取值为1,否则为0。

是否有人能够这样做并可以向我解释?

一个小例子可能是:

set.seed(123)
df <- data.frame(id = sample(1:10, 30, replace = TRUE),
             agegroup = sample(c("5054", "5559", "6065"), 30, replace = TRUE))

预期产量:

id  agegroup    dummy
 3     6065       1
 8     6065       1
 5     6065       1
 9     6065       1
10     5054       1
 1     5559       0
 6     6065       1
 9     5054       1
 6     5054       1
 5     5054       1
10     5054       1
 5     5559       1
 7     5559       1
 6     5559       1
 2     5054       1
 9     5054       1
 3     5054       1
 1     5559       0
 4     5054       0
10     6065       1
 9     5054       1
 7     5559       1
 7     6065       1
10     5054       1
 7     5559       1
 8     5054       1
 6     5054       1
 6     6065       1
 3     6065       1
 2     5559       1

6 个答案:

答案 0 :(得分:5)

选项是使用dplyr::group_by(id)并计算unique年龄组。您的数据包含idagegroup组合的重复行。

修改:更新了@Henrik

的评论
library(dplyr)

df %>% group_by(id) %>%
  mutate(dummy = as.integer(n_distinct(agegroup) > 1))    

# # A tibble: 30 x 3
# # Groups: id [10]
#      id agegroup dummy
#   <int> <fctr>   <int>
# 1     3 6065         1
# 2     8 6065         1
# 3     5 6065         1
# 4     9 6065         1
# 5    10 5054         1
# 6     1 5559         0
# 7     6 6065         1
# 8     9 5054         1
# 9     6 5054         1
# 10     5 5054         1
# # ... with 20 more rows

答案 1 :(得分:4)

这是data.table解决方案

library('data.table')
setDT(df)[, N := uniqueN(agegroup), by = .(id)][N == 1, N := 0 ][N > 1, N := 1]

setDT(df)[, N := as.integer( uniqueN(agegroup) > 1 ), by = .(id)]

答案 2 :(得分:3)

使用base R可以使用ave执行此操作。您只需要将factorcharacter变量agegroup强制转换为numeric

df$dummy <- ave(as.numeric(as.character(df$agegroup)), df$id, FUN = function(x) length(unique(x)) != 1)
head(df, 10)
#   id agegroup dummy
#1   3     6065     1
#2   8     6065     1
#3   5     6065     1
#4   9     6065     1
#5  10     5054     1
#6   1     5559     0
#7   6     6065     1
#8   9     5054     1
#9   6     5054     1
#10  5     5054     1

答案 3 :(得分:3)

另一个dplyr解决方案。 n_distinct是计算不同的数字。 (dummy > 1) + 0L用于评估数字是否大于1并转换为整数。

library(dplyr)

df2 <- df %>%
  group_by(id) %>%
  mutate(dummy = n_distinct(agegroup)) %>%
  mutate(dummy = (dummy > 1) + 0L) %>%
  ungroup()
df2
# # A tibble: 30 x 3
#       id agegroup dummy
#    <int> <fct>    <int>
#  1     3 6065         1
#  2     8 6065         1
#  3     5 6065         1
#  4     9 6065         1
#  5    10 5054         1
#  6     1 5559         0
#  7     6 6065         1
#  8     9 5054         1
#  9     6 5054         1
# 10     5 5054         1
# # ... with 20 more rows

答案 4 :(得分:2)

另一个带有ifelse的基本R解决方案:

df$dummy <- ifelse(df$id %in% names(which(lengths(tapply(df$agegroup, df$id, unique)) > 1)), 1, 0)

head(df)
  id agegroup dummy
1  3     6065     1
2  8     6065     1
3  5     6065     1
4  9     6065     1
5 10     5054     1
6  1     5559     0

答案 5 :(得分:0)

在基础R(也不保留行顺序)或dplyr(保留行顺序)

基础R

merge(df, transform(unique(df),dummy = as.numeric(duplicated(id)|duplicated(id,fromLast = T))))

#    id agegroup dummy
# 1   1     5559     0
# 2   1     5559     0
# 3  10     5054     1
# 4  10     5054     1
# 5  10     5054     1
# 6  10     6065     1
# 7   2     5054     1
# 8   2     5559     1
# 9   3     5054     1
# 10  3     6065     1
# 11  3     6065     1
# 12  4     5054     0
# 13  5     5054     1
# 14  5     5559     1
# 15  5     6065     1
# 16  6     5054     1
# 17  6     5054     1
# 18  6     5559     1
# 19  6     6065     1
# 20  6     6065     1
# 21  7     5559     1
# 22  7     5559     1
# 23  7     5559     1
# 24  7     6065     1
# 25  8     5054     1
# 26  8     6065     1
# 27  9     5054     1
# 28  9     5054     1
# 29  9     5054     1
# 30  9     6065     1

<强> dplyr

library(dplyr)
df %>%
  distinct %>% 
  mutate(dummy = as.numeric(duplicated(id)|duplicated(id,fromLast = T))) %>%
  inner_join(df,.)

#    id agegroup dummy
# 1   3     6065     1
# 2   8     6065     1
# 3   5     6065     1
# 4   9     6065     1
# 5  10     5054     1
# 6   1     5559     0
# 7   6     6065     1
# 8   9     5054     1
# 9   6     5054     1
# 10  5     5054     1
# 11 10     5054     1
# 12  5     5559     1
# 13  7     5559     1
# 14  6     5559     1
# 15  2     5054     1
# 16  9     5054     1
# 17  3     5054     1
# 18  1     5559     0
# 19  4     5054     0
# 20 10     6065     1
# 21  9     5054     1
# 22  7     5559     1
# 23  7     6065     1
# 24 10     5054     1
# 25  7     5559     1
# 26  8     5054     1
# 27  6     5054     1
# 28  6     6065     1
# 29  3     6065     1
# 30  2     5559     1