我的数据框类似于以下内容:
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)
我如何自动执行此操作,因为我的实际数据要大得多?
答案 0 :(得分:1)
Puginablanket,
请参阅下面的两个解决方案,一个使用plyr
包,另一个使用基本R的by
和do.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