2014-02-04 2 views
1

У меня есть сгруппированный набор данных, который я бы хотел перекалибровать, чтобы предоставить больше данных для анализа. По сути, я хочу добавить положительные эквиваленты наименьшего числа (отрицательного числа) в каждой группе ко всем числам внутри этой группы. Обратите внимание, что я хочу, чтобы это правило применялось только к группам, содержащим только отрицательные числа. Например, в приведенной ниже диаграмме A данных правило не нужно применять к A1, так как оно не содержит отрицательных чисел.Калибровка данных в R

Вот пример dataframe:

x_1 <- c("A1", "A1","A1", "B10", "B10", "B10","B10", "B500", "C100", "C100", "C100",  
"D40", "G100", "G100") 


z_1 <- c(1.1, 1.4, 1.6, -1.0, -2.2, 3, 2.3, 2.0, -3.4, -4.1, 2, 2, 2.4, -3.5) 


A <- data.frame(x_1, z_1) 

x_1 z_1 
A1 1.1 
A1 1.4 
A1 1.6 
B10 -1.0 
B10 -2.2 
B10 3.0 
B10 2.3 
B500 2.0 
C100 -3.4 
C100 -4.1 
C100 2.0 
D40 2.0 
G100 2.4 
G100 -3.5 

Результат Я хотел бы достичь дается dataframe В ниже:

b_2 <- c(1.1, 1.4, 1.6, 0, 1.2, 4.5, 5.2, 2.0, 0, 0.7, 6.1, 2.0, 0, 5.9) 

B <- data.frame(x_1, b_2) 


x_1 b_2 
A1 1.1 
A1 1.4 
A1 1.6 
B10 0.0 
B10 1.2 
B10 4.5 
B10 5.2 
B500 2.0 
C100 0.0 
C100 0.7 
C100 6.1 
D40 2.0 
G100 0.0 
G100 5.9 

Например, чтобы получить b_2[4:7], я добавил 2.2 ко всем другие номера и т. д.

Я начал с заказа данных с помощью G <- A[order(A$x_1, A$z_1), ], но я не знаю никакой другой функции, которую я могу для выполнения этой задачи. Функция совпадения здесь не будет иметь большого значения.

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

ответ

2

Данное решение для данных.

library(data.table) 
data.table(A)[, list(z_1, z_1a=z_1 - min(0, z_1)), by=x_1] 
#  x_1 z_1 z_1a 
# 1: A1 1.1 1.1 
# 2: A1 1.4 1.4 
# 3: A1 1.6 1.6 
# 4: B10 -1.0 1.2 
# 5: B10 -2.2 0.0 
# 6: B10 3.0 5.2 
# 7: B10 2.3 4.5 
# 8: B500 2.0 2.0 
# 9: C100 -3.4 0.7 
# 10: C100 -4.1 0.0 
# 11: C100 2.0 6.1 
# 12: D40 2.0 2.0 
# 13: G100 2.4 5.9 
# 14: G100 -3.5 0.0 
+0

+1 для' min (0, z_1) 'part :-) – A5C1D2H2I1M1N2O1R2T1

+0

@ BrodieG, большое спасибо за ваш ответ. –

2

Если я правильно понял ваш вопрос, вам не нужно сначала order. Просто используйте ave и min в within:

within(A, { 
    Mods <- ave(z_1, x_1, FUN = min) 
    Mods[Mods > 0] <- 0 
    Mods <- abs(Mods) 
    z_2 <- z_1 + Mods 
    rm(Mods) 
}) 
#  x_1 z_1 z_2 
# 1 A1 1.1 1.1 
# 2 A1 1.4 1.4 
# 3 A1 1.6 1.6 
# 4 B10 -1.0 1.2 
# 5 B10 -2.2 0.0 
# 6 B10 3.0 5.2 
# 7 B10 2.3 4.5 
# 8 B500 2.0 2.0 
# 9 C100 -3.4 0.7 
# 10 C100 -4.1 0.0 
# 11 C100 2.0 6.1 
# 12 D40 2.0 2.0 
# 13 G100 2.4 5.9 
# 14 G100 -3.5 0.0 

более прямой подход (что щедро заимствует @ ответ BrodieG в) должен изменить within материал к более простым:

with(A, z_1 - ave(z_1, x_1, FUN = function(x) min(0, min(x)))) 
+0

@ Ананда Махто, большое спасибо за ваш ответ - я понятия не имел, что существует функция ave. Я прочитаю об этом, –

+1

Адаптация ответа @ BrodieG на 'ave', мы можем сделать что-то вроде' с (A, z_1 - ave (z_1, x_1, FUN = function (x) min (0, min (x)))) ', чтобы получить нужные нам значения. – A5C1D2H2I1M1N2O1R2T1

+0

+ 1 для базы; Я считаю хорошей практикой придерживаться базы, если у вас есть чистое решение, которое я думаю с помощью трюка 'min', который вы очень сильно делаете. Я продолжаю забывать о 'ave' – BrodieG

Смежные вопросы