2011-01-03 5 views
4

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

Чтобы просто моя проблема, вот что мой кадр данных выглядит следующим образом:

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 

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

Я думаю, что я усложнять эту проблему, так что мне было интересно, как я могу ...

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

Дополнительное осложнение этой проблемы заключается в том, что это нужно выполнять в функции или динамически, так что мне не нужно вручную подмножать десятки «типов» (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: 

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

> 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 

меня тревожную мысль, что я собираюсь вокруг в кругах ...

+0

Вы фигурируете Выбрав себя, rls не работает на факторы. Но есть что-то странное. Я не могу воспроизвести вашу ошибку, она отлично работает для меня. Вы обновили до R 2.12.1? В любом случае, если у вас возникнут внутренние ошибки при установке plyr, было бы разумно потратить 2 минуты на переустановку R. Это действительно не займет больше времени. –

+0

@ Joris: Я еще не обновлялся до последней версии, так как я всегда немного колебался в этих вещах (2 минуты звучат достаточно обнадеживающе, чтобы гарантировать обновление. :)). У вас есть проблемы с воспроизведением «ошибки plyr» или ошибки из функции «unlist»? Я действительно надеюсь, что первое, иначе это говорит о том, что существуют различия в стандартных функциях R с версией 2.12.1, противоречащей 2.11. – Jura25

+1

Я не могу воспроизвести ни один из них, но я имел в виду функцию unlist. Я могу подтвердить, что 2.12 действительно немного отличается от 2.11, но все изменения, которые я нашел, были к лучшему. 2.12.1 работает бесперебойно и без ошибок для всего, что я знаю. Обновление, безусловно, является хорошим выбором. –

ответ

3

Две мысли:

1) можно использовать na.rm = T в rowSums

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 сумма на оригинальном dataframe

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

И, что более важно, получить dataframe в правильной форме:

> 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

Спасибо Joris, предложение 1 решает проблему NA в общей строке. Хорошо укажите ваше второе предложение. Согласование (например, по времени) - это что-то для дальнейшего анализа, и я не хотел долго задавать вопрос. Однако они уже сопоставлены в том смысле, что первое значение A произошло примерно за тот же период времени, что и первое значение B. – Jura25

+0

@Jura: тогда вы можете добавить некоторый идентификатор. Я адаптировал свой ответ на примере, позволяя использовать простой актерский состав. –

+0

@ Joris: Спасибо за вашу дальнейшую разработку, однако я получаю сообщение об ошибке при вводе «DF $ Total <- tapply (DF $ value, DF $ id, sum)», в котором говорится: «Ошибка в' $ <-. Data.frame '(' * tmp * '," Total ", value = c (6L, 8L, 10L, 12L,: замена имеет 6 строк, данные 10" или это что-то можно ожидать и зависит от пакета reshape? m, потому что я не могу установить пакет plyr (от которого зависит изменение) (R дает внутреннюю ошибку), и я бы предпочел не удалять и переустанавливать R, чтобы попытаться решить эту ошибку «plyr», если это абсолютно не необходимо для моего вопрос. (Извините, что беспокою вас снова) – Jura25

0
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)) 
Смежные вопросы