2016-11-28 3 views
3

использованием RStudio, у меня есть это:Добавление новой переменной dataframe одинаково

GROUP NUM 
A  45 
A  78 
A  79 
B  45 
B  47 
B  99 
C  28 
C  78 
C  54 

Я хочу, чтобы добавить новую переменную с именем AGENT, который:

AGENT=c("John", "Maria", "Pamela") 

Но проблема заключается в том, Я хочу, чтобы каждый из моих агентов был равномерно распределен между исходным фреймворком данных в соответствии с идентификатором. В основном, я хочу:

GROUP NUM AGENT 
A  45 John 
A  78 Maria 
A  79 Pamela 
B  45 John 
B  47 Maria 
B  99 Pamela 
C  28 John 
C  78 Maria 
C  54 Pamela 

Мой пример здесь является основным, потому что у меня столько групп, сколько у меня есть агенты. Однако в моем случае у меня может быть 70 каждой буквы (70 A, 70 B и 70 C) и все еще только 3 агента. Я все еще хочу, чтобы распространить как можно более равномерно ....

Например, если бы я имел 6 А, я бы:

GROUP NUM AGENT 
A  45 John 
A  78 Maria 
A  79 Pamela 
A  48 John 
A  97 Maria 
A  59 Pamela 
... 

И если у меня было 7, то седьмой будет назначен случайным образом или просто следующим в списке.

Любые идеи? Я мучился над этим. Заранее спасибо! : P

ответ

0

Я придумал немного сложный способ сделать это, используя индекс. Там может быть намного проще. Вот код:

library(dplyr) 
AGENT <- c("John", "Maria", "Paul") 

fun <- function(x){ 
x %>% mutate(agent=AGENT[((1:nrow(.) - 1) %% 3) + 1]) 
} 

df %>% 
    split(.$GROUP) %>% 
    lapply(fun) %>% 
    bind_rows() 

    GROUP NUM agent 
1  A 45 John 
2  A 78 Maria 
3  A 79 Paul 
4  B 45 John 
5  B 47 Maria 
6  B 99 Paul 
7  C 28 John 
8  C 78 Maria 
9  C 54 Paul 

Если не слишком много данных или длина GROUP не кратна AGENT, это создаст переменную следовать порядку AGENT.

df1 

GROUP NUM 
1  A 45 
2  A 78 
3  B 45 
4  C 28 

df1 %>% 
    split(.$GROUP) %>% 
    lapply(fun) %>% 
    bind_rows() 

    GROUP NUM agent 
1  A 45 John 
2  A 78 Maria 
3  B 45 John 
4  C 28 John 
+0

Потрясающе, просто и работает. Спасибо миллион раз! –

0

Попробуйте this-

# Data 
df <- data.frame("GROUP" = c("A","A","A","A","B","B","C","C","C"), 
      "NUM" = c(45,78,79,45,47,99,28,78,54)) 
AGENT=c("John", "Maria", "Pamela") 

# Assign agents 
df$agent <- NA 
groups <- levels(factor(df$GROUP)) 

lapply(groups, function(x) 
     { 
     df[df$GROUP == x, "agent"] <<- 
     c(rep(AGENT, as.integer(length(df[df$GROUP == x, "NUM"])/3)), 
      AGENT[0:(length(df[df$GROUP == x, "NUM"]) %% 3)]) 
     }) 

Если есть более 3-х агентов, заменить 3 в сценарии по длине (AGENT)

+0

Почему нисходящий для правильного ответа –

+0

Я не являюсь нисходящим, но я подозреваю, что использование '<< -' может вызвать тревогу для некоторых людей. – thelatemail

2

Если "или просто следующий в списке "подходит для любого переполнения, когда группа больше, вы можете воспользоваться переработкой векторов и просто сделать это в одном задании:

dat$newvar <- with(dat, ave(1:nrow(dat), GROUP, FUN=function(x) AGENT)) 
dat 
# GROUP NUM newvar 
#1  A 45 John 
#2  A 78 Maria 
#3  A 79 Pamela 
#4  B 45 John 
#5  B 47 Maria 
#6  B 99 Pamela 
#7  C 28 John 
#8  C 78 Maria 
#9  C 54 Pamela 

Просто игнорировать любые предупреждения, которые могли бы получить, когда группы не аккуратно подобраны по размеру AGENT

data.table может быть использован тоже в подобной манере:

library(data.table) 
setDT(dat) 
dat[, newvar2 := AGENT, by=GROUP] 
+0

Большое спасибо, очень хороший ответ. –