Генерация отдельных групп на основе пар вектор / столбец в R - PullRequest
2 голосов
/ 28 апреля 2019

СМ. ОБНОВЛЕНИЕ НИЖЕ:

Учитывая фрейм данных с двумя столбцами (x1, x2), представляющими пары объектов, я хотел бы создать группы, в которых все члены каждой группы соединены со всеми другими членами в этомгруппа.До сих пор мне удавалось генерировать группы, показывая все элементы в x2, которые связаны с каждым элементом в x1, но это оставляет меня с группами, в которых пара членов соединяется только с одним другим членом группы.Я с трудом отрываюсь от земли с этим ... Заранее спасибо за любую помощь, которую вы можете иметь.Пожалуйста, дайте мне знать, если я должен отредактировать этот пост, так как я новичок в Stack Overflow и плохо знаком с кодированием R.

x1 <- c("A", "B", "B", "B", "C", "C", "D", "D", "D", "E", "E")
x2 <- c("A", "B", "C", "D", "B", "C", "B", "D", "E", "D", "E")

df <- data.frame(x1, x2)

Я бы хотел перейти от этого df к выводу, похожему на df2.

group1 <- c("A")
group2 <- c("B", "C")
group3 <- c("B", "D")
group4 <- c("D", "E")

df2 <- data.frame(cbind.fill(group1, group2, group3, group4, fill =   "NULL"))

ОБНОВЛЕНИЕ:

Учитывая следующий набор данных ....

x1 <- c("A", "B", "B", "B", "C", "C", "D", "D", "D", "E", "E", "B", "C", "F")
x2 <- c("A", "B", "C", "D", "B", "C", "B", "D", "E", "D", "E", "F", "F", "F")

df <- data.frame(x1, x2)

.... Я хотел бы определить группыx1 / x2, где все объекты в указанной группе связаны со всеми другими объектами этой группы.

Это то, что я имею до сих пор (я уверен, что это пронизано ошибками из лучших практик, не стесняйтесь их вызывать. Я стремлюсь учиться) ...

n <- nrow(as.data.frame(unique(df$x1)))

RosterGuide <- as.data.frame(matrix(nrow = n , ncol = 1)) 
RosterGuide$V1 <- seq.int(nrow(RosterGuide))
RosterGuide$Object <- (unique(df$x1))
colnames(RosterGuide) <- c("V1","Object")
groups_frame <- matrix(, ncol= length(n), nrow = length(n))

for (loopItem in 1:nrow(RosterGuide)) {

object <- subset(RosterGuide$Object, RosterGuide$V1 == loopItem)
group <- as.data.frame(subset(df$x2, df$x1 == object))

groups_frame <- cbind.fill(group, groups_frame, fill = "NULL")
}

Groups <- as.data.frame(groups_frame)
Groups <- subset(Groups, select = - c(object))
colnames(Groups) <- RosterGuide$V1

Это дает фрейм данных 'Groups' ....

     1    2    3    4   5    6
1    F    D    B    B   B    A
2 NULL    E    D    C   C NULL
3 NULL NULL    E    F   D NULL
4 NULL NULL NULL NULL   F NULL

... что именно то, что я ищу, за исключением того, что если вы посмотрите на оригинальный df, объекты F и Dникогда не соединяются, что делает группу 5 недействительной.Кроме того, объекты B и E никогда не соединяются, что делает группу 3 недействительной.Допустимый результат должен выглядеть следующим образом ...

     1    2    3   4   5 
1    D    B    B   B   A    
2    E    D    C   C  NULL
3   NULL NULL NULL F  NULL

Вопрос: есть ли способ связать группы, перечисленные выше во фрейме данных «Группы», с исходным df, чтобы удалить группы с недопустимыми отношениями??Это действительно поставило меня в тупик.

Для контекста: что я действительно пытаюсь сделать, так это группировать элементы на основе парных соединений, полученных из сети узлов, где не все узлы соединены.

1 Ответ

1 голос
/ 28 апреля 2019

Вот один из способов сделать это в базе R, используя apply и unique

df <- data.frame(x1, x2, stringsAsFactors = F)
df <- df[df$x1 != df$x2, ]
unique(t(apply(df, 1, sort)))

  [,1] [,2]
3 "B"  "C" 
4 "B"  "D" 
9 "D"  "E" 

dplyr

df %>%
  dplyr::filter(x1 != x2) %>%
  dplyr::filter(!duplicated(paste(pmin(x1,x2), pmax(x1,x2), sep = "-")))

  x1 x2
1  B  C
2  B  D
3  D  E

data.table (может быть, есть другой лучший способ)

library(data.table)
as.data.table(df)[, .SD[x1 != x2]][, .GRP, by = .(x1 = pmin(x1,x2), x2 = pmax(x1,x2))]

   x1 x2 GRP
1:  B  C   1
2:  B  D   2
3:  D  E   3
...