если совпадение, список в векторе - PullRequest
1 голос
/ 25 февраля 2012

У меня есть фрейм данных с векторами в формате, подобном следующему

ID <- c("ID1", "ID1", "ID1", "ID2", "ID2", "ID3")  
ModNum <- c(1, 2, 3, 1, 2, 0)  
Amnt <- c(2.00, 3.00, 2.00, 5.00, 1.00, 5.00)  
df <- data.frame(ID, ModNum, Amnt)  

Мой желаемый результат - создать новый вектор во фрейме данных "Mod", который будет выглядеть примерно так:

ID   Mod  
ID1 ((1,2.00), (2, 3.00), (3, 2.00))  
ID2 ((1, 5.00), (2, 1.00))  
ID3 ((0, 5.00))  

Тогда я бы удалил лишние идентификаторы.

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

Как добавить пару ключ / значение переменной в объект списка?

`tapply ()` для возврата фрейма данных

Ответы [ 3 ]

1 голос
/ 26 февраля 2012

Вот решение с использованием split().

> ID.split <- split(df[-1], df$ID)
> ID.split
$ID1
  ModNum Amnt
1      1    2
2      2    3
3      3    2

$ID2
  ModNum Amnt
4      1    5
5      2    1

$ID3
  ModNum Amnt
6      0    5

> 
> flat.list <- lapply(ID.split, function(x)as.vector(t(x)))
> df <- data.frame(ID = names(flat.list))
> df$Mod <- flat.list
> df
   ID              Mod
1 ID1 1, 2, 2, 3, 3, 2
2 ID2       1, 5, 2, 1
3 ID3             0, 5

По моему мнению, вывод split() (то, что я назвал ID.split выше) является намного лучшей структурой данных, с которой можно работать с точки зрения программирования, чем конечный вывод, который вы запрашивали.

1 голос
/ 26 февраля 2012

Другое решение с пакетом plyr :

df$Mod <- sprintf("(%i, %.2f)", df$ModNum, df$Amnt) # prepare format

library(plyr)
ddply(df, .(ID), summarise, Mod=paste(Mod, collapse=", "))
#    ID                             Mod
# 1 ID1 (1, 2.00), (2, 3.00), (3, 2.00)
# 2 ID2            (1, 5.00), (2, 1.00)
# 3 ID3                       (0, 5.00)
0 голосов
/ 26 февраля 2012

Я бы порекомендовал организовать вывод немного по-другому, чтобы ваш фрейм данных с именем Mod содержал три элемента с именем ID1 , ID2, ID3, и каждый из этих элементов представлял собой матрицу с двумя столбцами.Так что ID2 будет

1 5.00<br> 2 1.00 Редактировать: использование split, как в другом ответе, намного чище.

тогда

Rgames> df<-as.list(1:length(unique(ID))) 
Rgames> names(df)<-unique(ID) 
Rgames> df$ID1<-cbind(ModNum[ID=="ID1"],Amnt[ID=="ID1"]) 
Rgames> df 
$ID1 
     [,1] [,2] 
[1,]    1    2 
[2,]    2    3 
[3,]    3    2 

$ID2
[1] 2

$ID3
[1] 3

И, конечно,Вы можете сделать цикл или lapply, чтобы заполнить все слоты ID.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...