基于多个变量合并行

时间:2016-12-11 00:08:12

标签: r

使用如下所示的数据集:

UserID       PartnerID  Happiness  Result
   1             2              30        1 
   2             1              20        1

正如您所看到的,这是重复的。我想把上面这两行合并成一行。我一直在搜索,但没有找到一个可以在这里工作的解决方案。我的理想输出是:

  UserID    PartnerID Happiness1   Happiness2    Result
     1          2            30         20         1

2 个答案:

答案 0 :(得分:2)

如果您不厌恶使用软件包,我建议您使用tidyverse。以下代码应该得到您想要的输出:

#install.packages("devtools")
#devtools::install_github("hadley/tidyverse")

library(tidyverse)


# Create a data.frame
dff <- structure(list(UserID = c(1, 2, 3, 4, 5, 6), 
                      PartnerID = c(2,1, 4, 3, 6, 5), 
                      Happiness = c(30, 20, 40, 50, 30, 20), 
                      Result = c(1, 1, 1, 1, 1, 1)), 
                 .Names = c("UserID", "PartnerID", "Happiness","Result"), 
                 row.names = c(NA, 6L), 
                 class = "data.frame")


# UserID PartnerID Happiness Result
# 1      2         30        1     
# 2      1         20        1     
# 3      4         40        1     
# 4      3         50        1     
# 5      6         30        1     
# 6      5         20        1  


# Reshape the data.frame
dff %>% mutate(grouper = paste(UserID, 
                               PartnerID, 
                               sep = "")) %>%
  mutate(grouper = unlist(map(strsplit(grouper,""),
                              function(x) paste0(sort(x),
                                                 collapse="")))) %>%
  group_by(grouper) %>%
  mutate(Happiness = toString(Happiness)) %>%
  ungroup() %>%
  dplyr::filter(!duplicated(grouper)) %>%
  separate(Happiness, into = c("Happiness1","Happiness2")) %>%
  select(-grouper)

此解决方案在%>%运算符的帮助下使用链式操作。

这里的想法是首先连接UserID和PartnerID列,然后grouper每行中的字符,创建一个分组列(称为sorting)。此时,grouper列应按排序顺序包含用户的ID和其合作伙伴的ID。这意味着用户及其合作伙伴都拥有grouper列中的值。因此,您可以继续使用group_by中的tidyverse功能按grouper列对数据进行分组。一旦您能够对数据进行分组,您就可以mutate Happiness列到一个字符串(这是toString函数正在执行的操作)。然后,此时您可以ungroup并过滤掉重复项。取出重复项后,您可以separateHappiness列分为两个不同的列:Happiness1Happiness2。最后,您可以使用grouper删除select(-grouper)列。

那应该产生:

# UserID PartnerID Happiness1 Happiness2 Result
# 1      2         30         20         1     
# 3      4         40         50         1     
# 5      6         30         20         1 

我希望这会有所帮助。

答案 1 :(得分:1)

也许是这样的,假设你的数据是(为了清楚起见,我只是添加了更多的玩具数据):

> df

# UserID PartnerID Happiness Result
  # 1         4        30      1
  # 2         3        20      0
  # 3         2        10      0
  # 4         1        15      1
  #10         13       20      1
  # 13        10       25      1
  # 5         6        10      0
  # 11        12       10      1
  # 6         5        10      0
  # 12        11       15      1

然后这个:

dups <- duplicated(t(apply(df[,c(1,2)],1,sort)))
cbind(df[, c(1,3)], df[match(df$UserID,df$PartnerID), c(1,3,4)])[dups,]

将为您提供所需的输出:

  # UserID Happiness UserID Happiness Result
#      3        10        2          20      0
#      4        15        1          30      1
#     13        25       10          20      1
#      6        10        5          10      0
#     12        15       11          10      1