向数据框中等量添加新变量

3

使用 RStudio,我有以下内容:

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")

但问题在于,我希望我的每个代理都能根据ID在初始数据框中均匀分布。基本上,我想要这样:

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个字母A、70个字母B和70个字母C,但仅有3个代理人。我仍然希望他们尽可能平均地分布...
例如,如果我有6个字母A,那么我会有:
GROUP NUM AGENT
A     45  John
A     78  Maria
A     79  Pamela
A     48  John
A     97  Maria
A     59  Pamela
...

如果我有7个,那么第7个会随机分配,或者只是在清单上的下一个。你有什么想法吗?我一直在为此苦恼。提前感谢!:P
3个回答

3
如果在组更大的情况下,“或者只是列表中的下一个。”适用于任何溢出,您可以利用向量循环并在一个赋值中完成它:
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]

我找到了一个类似问题的答案。它对我也起作用,但我想添加的向量包含日期。当我以这种方式添加时,日期会被转换为数字变量。只是在as.Date()中简单地包装with(...)并不起作用。它会抛出错误:“必须提供'origin'”。也许有什么想法? - Tingolfin
1
@Tingolfin - 你可以手动指定默认的 origin=,如 as.Date(ave(...), origin="1970-01-01"),或者在初始的 ave 调用中使用 Date 对象,例如 ave(rep(AGENT[1],nrow(dat)), dat$GROUP, FUN=function(x) AGENT) - thelatemail

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

试试这个 -

# 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替换为length(AGENT)。

我不是那个点踩者,但我怀疑使用 <<- 可能会引起一些人的警觉。 - thelatemail

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接