注意并重新编码重复项

时间:2015-04-28 23:41:53

标签: r

我的数据框类似于以下内容:

num <- c(1, 2, 3, 4)
name <- c("A", "B", "C", "A")
df <- cbind(num, name)

我希望将其转化为:

num <- c(1, 2, 3, 4)
name <- c("A1", "B", "C", "A2")
df <- cbind(num, name)

我如何自动执行此操作,因为我的实际数据要大得多?

4 个答案:

答案 0 :(得分:1)

Puginablanket,

请参阅下面的两个解决方案,一个使用plyr包,另一个使用基本R的bydo.call函数。

eg <- data.frame(num = c(1, 2, 3, 4, 5),
                 name = c("A", "B", "C", "A", "B"),
                 stringsAsFactors = FALSE)

do.call(rbind, by(eg, eg$name, function(x) {
  x$name2 <- paste0(x$name, 1:nrow(x))
  x
}))

plyr::ddply(eg, "name", function(x) {
  x$name2 <- paste0(x$name, 1:nrow(x))
  x
})

根据您的应用程序,创建一个跟踪此复制的单独列可能是有意义的(这样您以后不会使用字符串解析将其拉回来)。

答案 1 :(得分:1)

可能值得考虑内置的make.unique(),虽然它并没有完全符合OP的要求(它没有标记第一个重复的值,因此它可以运行多次连续)。由于name是一个因素,因此还需要一些额外的技巧:

df <- data.frame(num = c(1, 2, 3, 4),
                 name = c("A", "B", "C", "A"))
df <- transform(df, name=factor(make.unique(
                          as.character(name),sep="")))
##   num name
## 1   1    A
## 2   2    B
## 3   3    C
## 4   4   A1

答案 2 :(得分:0)

我将矩阵转换为数据框

df <- data.frame(num, name)

#Get duplicat names
ext <- as.numeric(ave(as.character(df$name) , df$name, 
                                   FUN=function(x) cumsum(duplicated(x))+1))

nms <- df$name[ext > 1]

#add into data   
df$newname <- ifelse( df$name %in% nms, paste0(df$name, ext), as.character(df$name))

答案 3 :(得分:0)

这是一个单行解决方案,假设您确实拥有data.frame而不是矩阵(矩阵是您的cbind()命令返回的内容):

df <- data.frame(num=1:4, name=c('A','B','C','A') );
transform(df,name=paste0(name,ave(c(name),name,FUN=function(x) if (length(x) > 1) seq_along(x) else '')));
##   num name
## 1   1   A1
## 2   2    B
## 3   3    C
## 4   4   A2