Сравнивая два столбца: логический - значение из столбца 1 также в столбце 2? - PullRequest
1 голос
/ 17 декабря 2011

Я не совсем понимаю, как это сделать. Скажем, у меня есть два столбца в кадре данных. В одном столбце числовой ряд в порядке (x), в другом указано какое-то значение из первого, или -1 (y). Это результаты соответствующего эксперимента, цель которого состоит в том, чтобы увидеть, сделаны ли несколько фотографий одного человека. В приведенном ниже примере есть 10 фотографий, но 6 уникальных людей. В столбце y отображается соответствующий x, если есть совпадение. у равен -1 для несоответствия (может также быть NA). Если на одного человека приходится более 2 фотографий, матч # будет самой последней записью (фото 1, 5 и 7 - это одно и то же лицо ниже). Группа - это период времени, в течение которого была сделана фотография (в группе нет совпадений!). Надеюсь, я правильно понял этот пример:

x <- c(1,2,3,4,5,6,7,8,9,10)
y <- c(-1,-1,-1,-1,1,-1,1,-1,2,4)
group <- c(1,1,1,2,2,2,3,3,3,3)
DF <- data.frame(x,y,group)

Я хотел бы создать новую переменную для именования уникальных людей и иметь окончательный набор данных с одной строкой на человека (то есть только 6 строк вместо 10), которая также включает информацию о группе. То есть если человек входит во все три группы, это может быть значение «111» или, если только в первой и последней группе это будет «101». Любые советы?

Спасибо за вопрос о полученном наборе данных. Я понял, что мои групповые объяснения были плохими, основываясь на фактических цифрах, которые я дал, поэтому я немного изменил результаты. Бонус тоже неплохо бы иметь, но не критично.

name <- c(1,2,3,4,6,8)
group_history <- as.character(c('111','101','100','011','010','001'))
bonus <- as.character(c('1,5,7','2,9','3','4,10','6','8')) 
results_I_want <- data.frame(name,group_history,bonus)

Мое слово, выше исправлено больше ошибок ...

Ответы [ 2 ]

2 голосов
/ 17 декабря 2011

Используя (обновленный) пример, который вы дали

x <- c(1,2,3,4,5,6,7,8,9,10)
y <- c(-1,-1,-1,-1,1,-1,1,-1,3,4)
group <- c(1,1,1,2,2,2,3,3,3,3)

DF <- data.frame(x,y,group)

Используйте x и y, чтобы создать отображение из более высоких чисел в более низкие числа, которые являются одним и тем же человеком.Обратите внимание, что names - это строка, несмотря на то, что она представляет собой строку цифр.

bottom.df <- DF[DF$y==-1,]
mapdown.df <- DF[DF$y!=-1,]
mapdown <- c(mapdown.df$y, bottom.df$x)
names(mapdown) <- c(mapdown.df$x, bottom.df$x)

Мы не знаем, сколько раз может потребоваться, чтобы все свелось к наименьшему числу, поэтому нужно использовать while loop.

oldx <- DF$x
newx <- mapdown[as.character(oldx)]
while(any(oldx != newx)) {
    oldx = newx
    newx = mapdown[as.character(oldx)]
}

Результатом является группа, к которой он принадлежит, имена с наименьшим номером из этого набора.

DF$id <- unname(newx)

Получить членство в группе сложнее.Использование reshape2 для преобразования этого в широкоформатный формат (по одному столбцу на группу), где столбец равен «1», если в нем что-то было, и «0», если нет.

library("reshape2")

wide <- dcast(DF, id~group, value.var="id", 
              fun.aggregate=function(x){if(length(x)>0){"1"}else{"0"}})

Наконец, вставьте этиЧленство «0» / «1» вместе, чтобы получить переменную группировки, которую вы описали.

wide$grouping = apply(wide[,-1], 1, paste, collapse="")

Результат:

> wide
  id 1 2 3 grouping
1  1 1 1 1      111
2  2 1 0 0      100
3  3 1 0 1      101
4  4 0 1 1      011
5  6 0 1 0      010
6  8 0 0 1      001

Пока нет «бонуса».

РЕДАКТИРОВАТЬ:

Чтобы получить информацию о бонусе, помогает повторить сопоставление, чтобы сохранить все.Если у вас много дел, это может быть медленным.

Замените часть oldx / newx на:

iterx <- matrix(DF$x, ncol=1)
iterx <- cbind(iterx, mapdown[as.character(iterx[,1])])
while(any(iterx[,ncol(iterx)]!=iterx[,ncol(iterx)-1])) {
    iterx <- cbind(iterx, mapdown[as.character(iterx[,ncol(iterx)])])
}

DF$id <- iterx[,ncol(iterx)]

Для создания бонусных данных, вы можете использовать

bonus <- tapply(iterx[,1], iterx[,ncol(iterx)], paste, collapse=",")
wide$bonus <- bonus[as.character(wide$id)]

Что дает:

> wide
  id 1 2 3 grouping bonus
1  1 1 1 1      111 1,5,7
2  2 1 0 0      100     2
3  3 1 0 1      101   3,9
4  4 0 1 1      011  4,10
5  6 0 1 0      010     6
6  8 0 0 1      001     8

Обратите внимание, что это не то же самое, что ваш пример вывода, но я не думаю, что ваш пример вывода является правильным (как вы можете иметь grouping_history из "000"?)

РЕДАКТИРОВАТЬ:

Теперь он согласен.

1 голос
/ 17 декабря 2011

Еще одно решение для бонусной переменной

f_bonus <- function(data=df){
  data_a <- subset(data,y== -1,select=x)
  data_a$pos <- seq(nrow(data_a))
  data_b <- subset(df,y!= -1,select=c(x,y))
  data_b$pos <- match(data_b$y, data_a$x)
  data_t <- rbind(data_a,data_b[-2])
  data_t <- with(data_t,tapply(x,pos,paste,sep="",collapse=","))
  return(data_t)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...