Подмножество в функции для вычисления итоговой строки - PullRequest
4 голосов
/ 03 января 2011

У меня есть фрейм данных с результатами для определенных инструментов, и я хочу создать новый столбец, который содержит итоги каждой строки. Поскольку у меня разное количество инструментов каждый раз, когда я запускаю анализ новых данных, мне нужна функция для динамического вычисления нового столбца с помощью итоговой суммы.

Для моей проблемы вот как выглядит мой фрейм данных:

    Type    Value
1   A   10
2   A   15
3   A   20
4   A   25
5   B   30
6   B   40
7   B   50
8   B   60
9   B   70
10  B   80
11  B   90

Моя цель - достичь следующего:

    A   B   Total
1   10  30  40
2   15  40  55
3   20  50  70
4   25  60  85
5       70  70
6       80  80
7       90  90

Я пробовал различные методы, но этот способ наиболее перспективен:

myList <- list(a = c(10, 15, 20, 25), b = c(30, 40, 50, 60, 70, 80, 90))
tmpDF <- data.frame(sapply(myList, '[', 1:max(sapply(myList, length))))
> tmpDF
   a  b
1 10 30
2 15 40
3 20 50
4 25 60
5 NA 70
6 NA 80
7 NA 90
totalSum <- rowSums(tmpDF)
totalSum <- data.frame(totalSum)
tmpDF <- cbind(tmpDF, totalSum)
> tmpDF
   a  b totalSum
1 10 30       40
2 15 40       55
3 20 50       70
4 25 60       85
5 NA 70       NA
6 NA 80       NA
7 NA 90       NA

Несмотря на то, что этому способу удалось объединить два фрейма данных различной длины, функция ‘rowSums’ в этом примере выдает неверные значения. Кроме того, мои исходные данные не представлены в виде списка, поэтому я не могу применить такое «решение».

Мне кажется, я слишком усложняю эту проблему, поэтому мне было интересно, как я могу ...

  • Подмножество данных из фрейма данных на основе «Типа»,
  • Вставить эти отдельные подмножества различной длины в новый фрейм данных,
  • Добавьте столбец «Всего» к этому фрейму данных, который является правильной суммой отдельные подмножества.

Дополнительным осложнением этой проблемы является то, что это должно быть сделано в функции или иным динамическим способом, так что мне не нужно вручную устанавливать десятки «типов» (A, B, C и и так далее) в моем фрейме данных.

Вот то, что я имею до сих пор, которое не работает, но иллюстрирует линии, о которых я думаю:

TotalDf <- function(x){
    tmpNumberOfTypes <- c(levels(x$Type))
    for( i in tmpNumberOfTypes){
        subSetofData <- subset(x, Type = i, select = Value)
        if( i == 1) {
        totalDf <- subSetOfData }
        else{
        totalDf <- cbind(totalDf, subSetofData)}
    }
    return(totalDf)
}

Заранее спасибо за любые мысли или идеи по этому поводу,

С уважением,

EDIT:

Благодаря комментарию Йориса (см. Ниже) я получил правильное направление, однако, пытаясь перевести его решение на мой фрейм данных, я столкнулся с дополнительными проблемами. Предложенный им ответ работает и дает мне следующую (правильную) сумму значений A и B:

> tmp78 <- tapply(DF$value,DF$id,sum)
> tmp78
 1  2  3  4  5  6 
 6  8 10 12  9 10 
> data.frame(tmp78)
  tmp78
1     6
2     8
3    10
4    12
5     9
6    10

Однако, когда я пробую это решение на моем фрейме данных, оно не работает:

> subSetOfData <- copyOfTradesList[c(1:3,11:13),c(1,10)]
> subSetOfData
   Instrument AccountValue
1         JPM         6997
2         JPM         7261
3         JPM         7545
11        KFT         6992
12        KFT         6944
13        KFT         7069
> unlist(sapply(rle(subSetOfData$Instrument)$lengths,function(x) 1:x))
Error in rle(subSetOfData$Instrument) : 'x' must be an atomic vector
> subSetOfData$InstrumentNumeric <- as.numeric(subSetOfData$Instrument)
> unlist(sapply(rle(subSetOfData$InstrumentNumeric)$lengths,function(x) 1:x))
     [,1] [,2]
[1,]    1    1
[2,]    2    2
[3,]    3    3
> subSetOfData$id <- unlist(sapply(rle(subSetOfData$InstrumentNumeric)$lengths,function(x) 1:x))
Error in `$<-.data.frame`(`*tmp*`, "id", value = c(1L, 2L, 3L, 1L, 2L,  : 
  replacement has 3 rows, data has 6

У меня тревожная идея, что я хожу по кругу ...

Ответы [ 2 ]

3 голосов
/ 03 января 2011

Две мысли:

1) вы можете использовать na.rm = T в строках суммы

2) Откуда ты знаешь, с кем нужно идти? Вы можете добавить индексирование.

Например:

DF <- data.frame(
  type=c(rep("A",4),rep("B",6)),
  value = 1:10,
  stringsAsFactors=F
)


DF$id <- unlist(lapply(rle(DF$type)$lengths,function(x) 1:x))

Теперь это позволяет легко tapply сумма на исходном кадре данных

tapply(DF$value,DF$id,sum)

И, что еще более важно, получите ваш фрейм данных в правильной форме:

> DF
   type value id
1     A     1  1
2     A     2  2
3     A     3  3
4     A     4  4
5     B     5  1
6     B     6  2
7     B     7  3
8     B     8  4
9     B     9  5
10    B    10  6

> library(reshape)
> cast(DF,id~type)
  id  A  B
1  1  1  5
2  2  2  6
3  3  3  7
4  4  4  8
5  5 NA  9
6  6 NA 10
0 голосов
/ 11 июля 2016
TV <- data.frame(Type = c("A","A","A","A","B","B","B","B","B","B","B")
             , Value = c(10,15,20,25,30,40,50,60,70,80,90)
             , stringsAsFactors = FALSE)

# Added Type C for testing
# TV <- data.frame(Type = c("A","A","A","A","B","B","B","B","B","B","B", "C", "C", "C")
#                  , Value = c(10,15,20,25,30,40,50,60,70,80,90, 100, 150, 130)
#                  , stringsAsFactors = FALSE)

lnType <- with(TV, tapply(Value, Type, length))
lnType <- as.integer(lnType)
lnType

id <- unlist(mapply(FUN = rep_len, length.out = lnType, x = list(1:max(lnType))))
(TV <- cbind(id, TV))

require(reshape2)
tvWide <- dcast(TV, id ~ Type)

# Alternatively
# tvWide <- reshape(data = TV,  direction = "wide", timevar = "Type",  ids = c(id, Type))

tvWide <- subset(tvWide, select = -id)

# If you want something neat without the <NA>
# for(i in 1:ncol(tvWide)){
#
#     if (is.na(tvWide[j,i])){
#       tvWide[j,i] = 0
#     }
#     
#   }
# }

tvWide
transform(tvWide, rowSum=rowSums(tvWide, na.rm = TRUE))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...