重组团队数据,在R中重复单个条目

时间:2015-01-10 01:02:43

标签: r

我当前的数据集如下所示:

Person  Team1     Team2     Team3   Team4   Team5
  1      10         11       NA      NA      NA  
  2      12         13       14      NA      NA
  3      15         16       NA      NA      NA
  1      11         14       NA      NA      NA

如您所见,有些人(即人1)在整个数据集中重复。给定人员的重复条目可以提供关于团队从属关系的新信息,并且还可以重复旧信息。我想要做的是创建一个数据集,其中每个人只占一行,并且他们的团队成员资格的信息都包含在该行中,并且不是多余的。例如:

Person  Team1   Team2   Team3   Team4   Team5
  1      10      11      14      NA      NA
  2      12      13      14      NA      NA
  3      15      16      NA      NA      NA

因此,即使人员1在数据集中被列为团队11两次,但它只在最终版本中出现一次。仅供参考:团队变量在我的实际数据集中一直到16,而不是停在5。

5 个答案:

答案 0 :(得分:3)

这是另一种可能性。会有优雅的方法来做到这一点。但是这会给你你所要求的结果。首先,我将数据分成Person并为每个人创建一个向量。其次,我搜索了每个向量中的唯一元素,并使长度为length(colnames(mydf))-1。第三,我将列表转换为数据框。最后,我为Person添加了一列,并更改了列名称。

ana <- lapply(split(mydf, mydf$Person), function(x) c(as.matrix(x[,-1])))
bob <- lapply(lapply(ana, unique), function(y) y[1:length(colnames(mydf))-1])
cathy <- data.frame(do.call(rbind, bob))
dan <- cbind(unique(mydf$Person), cathy)
names(dan) <- names(mydf)

#  Person Team1 Team2 Team3 Team4 Team5
#1      1    10    11    14    NA    NA
#2      2    12    13    14    NA    NA
#3      3    15    16    NA    NA    NA

数据

mydf <- structure(list(Person = c(1L, 2L, 3L, 1L), Team1 = c(10L, 12L, 
15L, 11L), Team2 = c(11L, 13L, 16L, 14L), Team3 = c(NA, 14L, 
NA, NA), Team4 = c(NA, NA, NA, NA), Team5 = c(NA, NA, NA, NA)), .Names = c("Person", 
"Team1", "Team2", "Team3", "Team4", "Team5"), class = "data.frame", row.names = c(NA, 
-4L))

答案 1 :(得分:3)

您可以尝试data.table。通过setDT将“data.frame”转换为“data.table”,从“wide”更改为“long”形式,通过“Person”获取“Team”列的unique值, (unique(unlist(.SD))),为每个“人物”创建序列列(“V2”),并通过dcast.data.table

将其重新整形为“宽”
library(data.table)
dt1 <- dcast.data.table(setDT(df)[, unique(unlist(.SD)) ,
          by=Person][, V2:=paste0('Team', 1:.N), by=Person],
                                Person~V2, value.var='V1')
dt1 
 #  Person Team1 Team2 Team3 Team4
 #1:      1    10    11    14    NA
 #2:      2    12    13    14    NA
 #3:      3    15    16    NA    NA

如果您需要“Team5”,“Team6”等,请创建“团队”名称的向量,使用setdiff,然后将结果向量分配给NA

indx <- setdiff(paste0('Team', 1:5), colnames(dt1))
dt1[,(indx):=NA]
dt1
#   Person Team1 Team2 Team3 Team4 Team5
#1:      1    10    11    14    NA    NA
#2:      2    12    13    14    NA    NA
#3:      3    15    16    NA    NA    NA

答案 2 :(得分:1)

我不是非常精通R,所以这段代码可能很草率,但我认为你最好的选择是创建一个包含团队成员列表的新列,例如:

data$teams = with(data, c(Team1, Team2, Team3, Team4[...]))

其他队伍的其他地方。从那里,您可以使用Person作为键来聚合列,并执行一些不列名/唯一来消除重复:

byperson = aggregate(data, by=list(data$Person), FUN=list)
byperson$teams = sapply(sapply(byperson$teams, unlist), unique)

按人员聚合列表,将重复行(我在第一位中创建的列表)与list函数组合在一起,后者生成列表列表。第二行然后只是通过byperson $ teams中的每个列表列表,首先在它们上面运行unlist以将它们放入一个平面列表,然后unique以消除欺骗。

可能有更好,更优雅的方法,可能使用melt库,但这是你必须要做的基本想法 - 将16列重新格式化为一列列表,或者将它扩展为行,每个“成员资格”一个。后一种格式是R在我的经验中倾向于“偏好”,如下所示:

Person Team
     1   10
     1   11
     1   14
     2   12
     2   13
     2   14
     3   15
     3   16

但我不确定如何从您的数据中获取。列表列表可能是合适的,这取决于您尝试对数据执行的操作,但是在您的示例中构建的数据在R中执行任何有用的操作将非常困难。

答案 3 :(得分:1)

以下是基于cast包中的melt / reshape2函数的解决方案

library(reshape2)

# Make the data tidy
d.melt <- melt(mydf,id.vars = 'Person')

# Remove duplicates
d.uniq <- d.melt[!duplicated(d.melt[,c('Person','value')]),]

# renumber the teams
d.uniq$team <- ave(d.uniq$Person,d.uniq$Person,FUN=function(i) paste0('Team',seq_along(i)))

# cast into the desired 'wide' format
d.result <- dcast(d3,Person~team,value.var = 'value')

结果是:

#   Person Team1 Team2 Team3 Team4
# 1      1    10    11    14    NA
# 2      2    12    13    14    NA
# 3      3    15    16    NA    NA

如果结果必须包含一定数量的列:

all.teams <- paste0('Team',1:16)
d.result[,all.teams[!all.teams %in% colnames(d.result)]]=NA

答案 4 :(得分:0)

使用dplyrtidyr包的另一种方式。

x <- read.table(text = "Person  Team1     Team2     Team3   Team4   Team5
  1      10         11       NA      NA      NA  
  2      12         13       14      NA      NA
  3      15         16       NA      NA      NA
  1      11         14       NA      NA      NA", header = TRUE)

library(dplyr)
library(tidyr)

x %>%
gather(meaningless_column, Team, -Person) %>%
select(-meaningless_column) %>%
filter(!is.na(Team)) %>%
distinct %>%
arrange(Person, Team) %>%
group_by(Person) %>%
mutate(Index = paste0("Team_", seq_along(Team))) %>%
ungroup %>%
spread(Index, Team)

结果:

  Person Team_1 Team_2 Team_3
1      1     10     11     14
2      2     12     13     14
3      3     15     16     NA

它会根据需要创建尽可能多的Team_n列。