2014-09-26 104 views
0

我的数据框DF貌似值数据帧添加列:基于其他列

ID Name1 Name2 Group  
1234 A1  x 
1234 A4  w 
1234 A3  q 
1234 A  A 
1234 A2  z 
5678 B3  s 
5678 B  B 
... 

我需要添加一列GroupName1每个ID相匹配的行中的ID其中Name1 == Name2

所以逻辑是检查是否Name1 == Name2,记住该行的ID和Name1值,然后对于每个具有该ID的行,将Name1值放在Group列的每一行中。

结果应该是这样的:

ID Name1 Name2 Group  
1234 A1  x  A 
1234 A4  w  A 
1234 A3  q  A 
1234 A  A  A 
1234 A2  z  A 
5678 B3  s  B 
5678 B  B  B 
... 

我不知道如何在数据帧,但并从不同的ID很多行做到这一点。我不想使用循环。

mutate()lapply()也许?

我可以看到如何为Name1 == Name2的行在Group列中添加Name1值,但是如何为所有匹配的ID滚动备份?

回答

3

,你可以做一个单一的线,采用data.table

DT[, Group := Name1[Name1 == Name2], by=ID] 

全部细节:

library(data.table) 

DT <- as.data.table(DF) 

DT[, Group := Name1[Name1 == Name2], by=ID] 

    ID Name1 Name2 Group 
1: 1234 A1  x  A 
2: 1234 A4  w  A 
3: 1234 A3  q  A 
4: 1234  A  A  A 
5: 1234 A2  z  A 
6: 5678 B3  s  B 
7: 5678  B  B  B 
8: 1589  C  x NA 
9: 1589  C  y NA 



## if `Name1`, `Name2` are NOT characters, use 
DT[, Name1 := as.character(Name1)] 
DT[, Name2 := as.character(Name2)] 
1

试试这个

x <- merge(x, x[x$Name1 == x$Name2, 1:2], by.x = "ID", by.y = "ID") 
names(x)[4] <- "Group" 
#  ID Name1.x Name2 Group 
# 1 1234  A1  x  A 
# 2 1234  A4  w  A 
# 3 1234  A3  q  A 
# 4 1234  A  A  A 
# 5 1234  A2  z  A 
# 6 5678  B3  s  B 
# 7 5678  B  B  B 
0

另外一个可能性:

unsplit(lapply(split(df, df$ID), function(x) { 
    x$Group <- if(any(y <- x$Name1 %in% x$Name2)) x$Name2[y] else NA 
    x 
}), df$ID) 

    ID Name1 Name2 Group 
1 1234 A1  x  A 
2 1234 A4  w  A 
3 1234 A3  q  A 
4 1234  A  A  A 
5 1234 A2  z  A 
6 5678 B3  s  B 
7 5678  B  B  B 
9 1589  C  x <NA> 
10 1589  C  y <NA> 

数据

df <- 
structure(list(ID = c("1234", "1234", "1234", "1234", "1234", 
"5678", "5678", "1589", "1589"), Name1 = structure(c(2L, 5L, 
4L, 1L, 3L, 7L, 6L, 8L, 8L), .Label = c("A", "A1", "A2", "A3", 
"A4", "B", "B3", "C"), class = "factor"), Name2 = structure(c(6L, 
5L, 3L, 1L, 7L, 4L, 2L, 6L, 8L), .Label = c("A", "B", "q", "s", 
"w", "x", "z", "y"), class = "factor")), .Names = c("ID", "Name1", 
"Name2"), row.names = c("1", "2", "3", "4", "5", "6", "7", "9", 
"10"), class = "data.frame") 
+0

我得到一个错误说“组长度为零,但数据长度是> 0“ – brno792 2014-09-26 20:48:55

0

会不会有永远Name1之间的一个(也是唯一一个)匹配和每个ID有Name2

如果是这样,你可以(使用df在@Richard斯克里芬的答案)使用mutatedplyr此:

require(dplyr) 

df[1:7,] %>% 
    group_by(ID) %>% 
    mutate(Group = Name1[Name1 %in% Name2]) 

如果有可能是一个或每个ID不匹配,可以添加在ifelse声明中处理不匹配的情况。

df %>% 
    group_by(ID) %>% 
    mutate(Group = ifelse(any(Name1 %in% Name2), 
          as.character(Name1)[Name1 %in% Name2], "NA")) 
+0

例如,当我运行mutate()时出现错误:”不兼容的大小(3),期望4(组大小)“。 ID是左侧一些其他列的子集。但是,我在我的group_by() – brno792 2014-09-26 21:28:50

+0

中包括那些是的,应该总是只有一个匹配每个ID – brno792 2014-09-26 21:30:33

+0

@ brno792你可以'输入'你的数据集(或它的一部分)到你的问题?这听起来像是我没有考虑过的其他结构。 – aosmith 2014-09-26 21:36:16