2015-06-18 1 views
1

У меня есть dataframe как этотR: Создать 2 колонки с разностными и проценты значения другого столбца

ID <- c(101,101,101,102,102,102,103,103,103) 
Pt_A <- c(50,100,150,20,30,40,60,80,90) 
df <- data.frame(ID,Pt_A) 

+-----+------+ 
| ID | Pt_A | 
+-----+------+ 
| 101 | 50 | 
| 101 | 100 | 
| 101 | 150 | 
| 102 | 20 | 
| 102 | 30 | 
| 102 | 40 | 
| 103 | 60 | 
| 103 | 80 | 
| 103 | 90 | 
+-----+------+ 

Я хочу создать 2 новых столбцов со значениями вычисленных из столбца Pt_A.

df$Del_Pt_A <- NthRow(Pt_A) - 1stRow(Pt_A) grouped by ID, where n = 1,2,...n 
df$Perc_Pt_A <- NthRow(Del_Pt_A)/1stRow(Pt_A) grouped by ID, where n = 1,2,...n 

Вот мой желаемый результат

+-----+------+---------+-----------+ 
| ID | Pt_A | Del_Pt_A | Perc_Pt_A| 
+-----+------+---------+-----------+ 
| 101 | 50 | 0  | 0   | 
| 101 | 100 | 50  | 1.0  | 
| 101 | 150 | 100  | 2.0  | 
| 102 | 20 | 0  | 0   | 
| 102 | 30 | 10  | 0.5  | 
| 102 | 40 | 20  | 1.0  | 
| 103 | 60 | 0  | 0   | 
| 103 | 80 | 20  | 0.3  | 
| 103 | 90 | 30  | 0.5  | 
+-----+------+---------+-----------+ 

я в настоящее время получить желаемый результат в MS Excel, но я хочу, чтобы научиться делать это в R, чтобы сделать свою работу эффективной. Я сталкивался с пакетами, такими как dplyr, plyr, data.table и т. Д., Но я не мог решить это с помощью этих. Может кто-нибудь, пожалуйста, помогите мне разобраться, как обойти это.

+1

Fyi, ' NthRow (Del_Pt_A)/1stRow (Pt_A) 'упрощается до' NthRow (Pt_A)/1stRow (Pt_A) - 1'. Вот почему вы видите это в ответах ниже. – Frank

+1

Спасибо @Frank, я заметил это сейчас. – Sharath

ответ

4

Вот data.table путь:

library(data.table) 
setDT(df)[,`:=`(
    del  = Pt_A - Pt_A[1], 
    perc  = Pt_A/Pt_A[1]-1 
),by=ID] 

который дает

ID Pt_A del  perc 
1: 101 50 0 0.0000000 
2: 101 100 50 1.0000000 
3: 101 150 100 2.0000000 
4: 102 20 0 0.0000000 
5: 102 30 10 0.5000000 
6: 102 40 20 1.0000000 
7: 103 60 0 0.0000000 
8: 103 80 20 0.3333333 
9: 103 90 30 0.5000000 
+3

Отличное решение! Я собираюсь использовать это. Data.table настолько удобна и легко интерпретируется. – Sharath

2

Вот еще один вариант в базе R:

cbind(df, 
     do.call(rbind,by(df,df$ID, 
    function(x) 
      setNames(data.frame(x$Pt_A-x$Pt_A[1], 
         x$Pt_A/x$Pt_A[1]-1), 
        c('Del_Pt_A','Perc_Pt_A'))))) 

#  ID Pt_A Del_Pt_A Perc_Pt_A 
# 101.1 101 50  0 0.0000000 
# 101.2 101 100  50 1.0000000 
# 101.3 101 150  100 2.0000000 
# 102.1 102 20  0 0.0000000 
# 102.2 102 30  10 0.5000000 
# 102.3 102 40  20 1.0000000 
# 103.1 103 60  0 0.0000000 
# 103.2 103 80  20 0.3333333 
# 103.3 103 90  30 0.5000000 

Я использую:

  • by применить функцию группой, результатом является список
  • do.call(rbind, list_by) преобразовать список в data.frame
  • cbind добавить результат к исходному data.frame
+0

Вы можете сделать с помощью (x, ...) ', чтобы избавиться от' x $ 'и' data.frame (del = ..., perc = ...) ', чтобы избавиться от' setNames' ...? – Frank

+1

@Frank, конечно. Это было решение data.table, которое я преобразовал в базовое решение в последнюю минуту .... Хотя, я буду отмечать использование 'with' (личное предпочтение), но, безусловно, преобразую' '' to '['. – agstudy