2013-12-06 3 views
9

У меня есть кадр данных, который имеет 2 столбца.Заполнение кадра данных с предыдущим значением строки

column1 имеет случайные числа в COLUMN2 место держит колонки для того, что я хочу колонка3 выглядеть

random temp 
0.502423373 1 
0.687594055 0 
0.741883739 0 
0.445364032 0 
0.50626137 0.5 
0.516364981 0 
... 

Я хочу, чтобы заполнить колонка3 поэтому она занимает последнее ненулевое число (1 или 0,5 в этом примере) и непрерывно заполняет следующие строки этим значением, пока оно не попадет в строку с другим номером. то он повторяет процесс для всего столбца.

random  temp state 
0.502423373 1 1 
0.687594055 0 1 
0.741883739 0 1 
0.445364032 0 1 
0.50626137 0.5 0.5 
0.516364981 0 0.5 
0.807804708 0 0.5 
0.247948445 0 0.5 
0.46573337 0 0.5 
0.103705154 0 0.5 
0.079625868 1 1 
0.938928944 0 1 
0.677713019 0 1 
0.112231619 0 1 
0.165907178 0 1 
0.836195267 0 1 
0.387712998 1 1 
0.147737077 0 1 
0.439281543 0.5 0.5 
0.089013503 0 0.5 
0.84174743 0 0.5 
0.931738707 0 0.5 
0.807955172 1 1 

спасибо за любую помощь

ответ

11

Может быть, вы можете использовать na.locf из пакета «зоопарка» после установки значения «0» в NA. Если предположить, что data.frame называется «mydf»:

mydf$state <- mydf$temp 
mydf$state[mydf$state == 0] <- NA 

library(zoo) 
mydf$state <- na.locf(mydf$state) 
#  random temp state 
# 1 0.5024234 1.0 1.0 
# 2 0.6875941 0.0 1.0 
# 3 0.7418837 0.0 1.0 
# 4 0.4453640 0.0 1.0 
# 5 0.5062614 0.5 0.5 
# 6 0.5163650 0.0 0.5 

Если были NA значения в исходном data.frame в колонке «Темп», и вы хотите, чтобы держать их в качестве NA в вновь созданном «состоянии» колонку тоже, о которой легко позаботиться. Просто добавьте еще одну строку, чтобы повторно ввести NA значения:

mydf$state[is.na(mydf$temp)] <- NA 
+0

Я думаю, что это было бы плохо, если в данных уже нет данных. Но если это работает, это тоже хорошо. –

+0

@NealFultz, и этот комментарий требует голосования? Очень легко решить вашу озабоченность по поводу комментария. (Я предполагаю, что вы хотите, чтобы значение в сгенерированной переменной состояния было «NA», если оно было «NA» в переменной «temp».Обратите внимание, что я не касаюсь переменной temp, поэтому у меня все еще есть легкий доступ к этой информации.) – A5C1D2H2I1M1N2O1R2T1

+0

И если у вас есть NA рядом с 0s? –

0

Петля по следующим направлениям должны сделать трюк для вас -

for(i in seq(nrow(df))) 
{ 
    if (df[i,"v1"] == 0) df[i,"v1"] <- df[i-1,"v1"] 
} 

Выход -

> df 
    v1 somedata 
1 1  33 
2 2  24 
3 1  36 
4 0  49 
5 2  89 
6 2  48 
7 0  4 
8 1  98 
9 1  60 
10 2  76 
> 
> for(i in seq(nrow(df))) 
+ { 
+ if (df[i,"v1"] == 0) df[i,"v1"] <- df[i-1,"v1"] 
+ } 
> df 
    v1 somedata 
1 1  33 
2 2  24 
3 1  36 
4 1  49 
5 2  89 
6 2  48 
7 2  4 
8 1  98 
9 1  60 
10 2  76 
3

Вот интересным способом с функцией Reduce.

temp = c(1,0,0,0,.5,0,0,0,0,0,1,0,0,0,0,0,1,0,0.5,0,0,0,1) 
fill_zero = function(x,y) if(y==0) x else y 
state = Reduce(fill_zero, temp, accumulate=TRUE) 

Если вы беспокоитесь о скорости, вы можете попробовать Rcpp.

library(Rcpp) 
cppFunction(' 
    NumericVector fill_zeros(NumericVector x) { 
    for(int i=1; i<x.size(); i++) 
    if(x[i]==0) x[i] = x[i-1]; 
    return x; 
    } 
') 
state = fill_zeros(temp) 
0

Я предлагаю использовать функции кодирования длины пробега, это естественный способ борьбы со стейками в наборе данных. Использование @ пример вектора Кевина:

temp = c(1,0,0,0,.5,0,0,0,0,0,1,0,0,0,0,0,1,0,0.5,0,0,0,1) 
y <- rle(temp) 
#str(y) 
#List of 2 
# $ lengths: int [1:11] 1 3 1 5 1 5 1 1 1 3 ... 
# $ values : num [1:11] 1 0 0.5 0 1 0 1 0 0.5 0 ... 
# - attr(*, "class")= chr "rle" 


for(i in seq(y$values)[-1]) { 
    if(y$values[i] == 0) { 
     y$lengths[i-1] = y$lengths[i] + y$lengths[i-1] 
     y$lengths[i] = 0 
    } 
} 

#str(y) 
#List of 2 
# $ lengths: num [1:11] 4 0 6 0 6 0 2 0 4 0 ... 
# $ values : num [1:11] 1 0 0.5 0 1 0 1 0 0.5 0 ... 
# - attr(*, "class")= chr "rle" 

inverse.rle(y) 
# [1] 1.0 1.0 1.0 1.0 0.5 0.5 0.5 0.5 0.5 0.5 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.5 
# [20] 0.5 0.5 0.5 1.0 
+1

Вам нужен какой-то соус данных A-1, чтобы пойти с этими стейками? : -0 –

3

Кроме того, если я не с видом на что-то, это похоже на работу:

DF$state2 <- ave(DF$temp, cumsum(DF$temp), FUN = function(x) x[x != 0]) 
DF 
#  random temp state state2 
#1 0.50242337 1.0 1.0 1.0 
#2 0.68759406 0.0 1.0 1.0 
#3 0.74188374 0.0 1.0 1.0 
#4 0.44536403 0.0 1.0 1.0 
#5 0.50626137 0.5 0.5 0.5 
#6 0.51636498 0.0 0.5 0.5 
#7 0.80780471 0.0 0.5 0.5 
#8 0.24794844 0.0 0.5 0.5 
#9 0.46573337 0.0 0.5 0.5 
#10 0.10370515 0.0 0.5 0.5 
#11 0.07962587 1.0 1.0 1.0 
#12 0.93892894 0.0 1.0 1.0 
#13 0.67771302 0.0 1.0 1.0 
#14 0.11223162 0.0 1.0 1.0 
#15 0.16590718 0.0 1.0 1.0 
#16 0.83619527 0.0 1.0 1.0 
#17 0.38771300 1.0 1.0 1.0 
#18 0.14773708 0.0 1.0 1.0 
#19 0.43928154 0.5 0.5 0.5 
#20 0.08901350 0.0 0.5 0.5 
#21 0.84174743 0.0 0.5 0.5 
#22 0.93173871 0.0 0.5 0.5 
#23 0.80795517 1.0 1.0 1.0 
+0

Я думаю, что 'ave (DF $ temp, cumsum (DF $ temp), FUN = sum)' должен работать. – kdauria

+0

@ Кевин: Да, ты прав! В этом случае также выполняется 'sum'ming значений. И, возможно, это тоже быстрее, потому что он избегает обращения к логике перед индексированием? Хотя, я все же мог бы предпочесть 'x [x! = 0]', потому что он точно определяет, что такое функция 'ave'raging. –

4

Вдохновленный раствором @Ananda Mahto, это адаптация внутреннего код na.locf, который работает непосредственно с 0 вместо NA s. Тогда вам не нужен пакет zoo, и вам не нужно делать предварительную обработку изменения значений до NA. Тесты показывают, что это примерно в 10 раз быстрее, чем исходная версия.

locf.0 <- function(x) { 
    L <- x!=0 
    idx <- c(0, which(L))[cumsum(L) + 1] 
    return(x[idx]) 
} 
mydf$state <- locf.0(mydf$temp) 
+0

Умная мысль изменить 'na.locf'. +1 – A5C1D2H2I1M1N2O1R2T1

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