2017-12-08 4 views
0

同じ列の前の行に基づいてテスト値(1または0)で列を変更しようとしています。別の列。 1行または2行の場合は問題ではありませんが、最大50行の値を「先導」する必要があり、コードを作成するのが面倒です。同じ列の前の行の値に基づいてdplyr lag()を使用して列に値を追加する方法

df <- data.frame(matrix(nrow = 10, ncol = 3)) 
names(df) <- c("letter", "color", "test") 
df[, 1] <- c("a", "a", "b", "b", "b", "b", "b", "c", "c", "c") 
df[1:2, 2] <- c("blue") 
df[8:10, 2] <- c("green") 
df[, 3] <- c(0, 0, 1, 0, 0, 0, 0, 0, 0, 0) 

DF:

letter color test 
1  a blue 0 
2  a blue 0 
3  b <NA> 1 
4  b <NA> 0 
5  b <NA> 0 
6  b <NA> 0 
7  b <NA> 0 
8  c green 0 
9  c green 0 
10  c green 0 

私の実際のデータは、この問題のために再作成することはむしろ難しいですが、私は、コードの最初のビットの後でよどここのdfは - 私がいることを認識していますテスト列の「1」(df[3, 3])は私の問題が始まる場所です。私は今、 "色"がNAでなく、 "文字"が "b"でなくなるまで、テスト列の1を "導く"必要があります。次のような

コードは(私の例では、それは意志のように見えますが)十分ではありません。私の目的のために

... mutate(test = ifelse(letter == "b" & is.na(color), 1, test) 

を、私は1を「リード」するには、次のコードを使用する必要があります。

letter color test 
1  a blue 0 
2  a blue 0 
3  b <NA> 1 
4  b <NA> 1 
5  b <NA> 0 
6  b <NA> 0 
7  b <NA> 0 
8  c green 0 
9  c green 0 
10  c green 0 

df <- df %>% 
    mutate(test = ifelse(lag(test) == 1 & is.na(color), 1, test)) 

しかし、このコードを実行すると、単一の次の列を移入しますこれを達成するために、私は同じmutateコマンドを50回(同じ列で実行)のように書いています。たとえば、次のように

df <- df %>% 
    mutate(test = ifelse(lag(test) == 1 & is.na(color), 1, test), 
     test = ifelse(lag(test) == 1 & is.na(color), 1, test), 
     test = ifelse(lag(test) == 1 & is.na(color), 1, test), 
     test = ifelse(lag(test) == 1 & is.na(color), 1, test), 
     test = ifelse(lag(test) == 1 & is.na(color), 1, test)) 

これは、所望の結果を返します。

letter color test 
1  a blue 0 
2  a blue 0 
3  b <NA> 1 
4  b <NA> 1 
5  b <NA> 1 
6  b <NA> 1 
7  b <NA> 1 
8  c green 0 
9  c green 0 
10  c green 0 

をしかし、これは非常に不器用で、潜在的に、私は十分にmutateコマンドを複製書いていないという可能性を開いたままに。

dplyr(または別の方法)を使用してこれを行う方法はありますか? forループはおそらく仕事を終わらせるかもしれませんが、私はそれが必要であるとは確信していません。さらに、私はまだRを学んでおり、実際にapplyファミリの機能を理解することはできませんでした。この状況でapplyを使用することはできますか?

+0

'次のようなコードは'私はそれが変更に良いだろうと思います(私の例では、それは意志のように見えますが)十分ではありません他の人が誤解されないようにする例 – akrun

+0

いいえ。私は自分のデータに沿った簡単な例をどのように作成するのか本当に分かりません。私は他の何かに取り組むでしょう... –

答えて

1

私はあなたが正しく、あなたがあなたがlagですべてを複雑に上かもしれない

library(dplyr) 
df %>% group_by(letter, color) %>% 
    mutate(test = first(test)) 


#sample data 
> dput(df) 
structure(list(letter = structure(c(1L, 1L, 2L, 2L, 2L, 2L, 2L, 
3L, 3L, 3L), .Label = c("a", "b", "c"), class = "factor"), color = structure(c(2L, 
2L, 1L, 1L, 1L, 1L, 1L, 3L, 3L, 3L), .Label = c("<NA>", "blue", 
"green"), class = "factor"), test = c(0L, 0L, 1L, 0L, 0L, 0L, 
0L, 0L, 0L, 0L)), .Names = c("letter", "color", "test"), class = "data.frame", row.names = c("1", 
"2", "3", "4", "5", "6", "7", "8", "9", "10")) 
+0

OPによってはあまり明確ではありませんが、あなたの方法は失敗すると思います。第一のものではなく、第二のエントリは1です。つまり、 'df $ test [ 3] < - 0'と 'df $ test [4] < - 1'です。 – Sotos

+0

@Sotosが同意します! OPは介入して彼のUCを明確にする必要があると思われる(しかし、それはうまくいくはずのデータで)。 – Prem

+0

遅れて申し訳ありません。私はまだ私が達成する必要のあるより良い例を見つけようとしています。私は残念ながら "文字"変数でグループ化することでこれを達成できません。混乱させて申し訳ありません。 –

1

を使用して最終結果を達成することができますあなたの例を考えると理解している場合。 letterでグループ化すると、あなたの色がNAfill残りのすべての位置(1の後)にすることができます。

与え
library(tidyverse) 

df %>% 
group_by(letter) %>% 
mutate(test = replace(test, is.na(color) & test != 1, NA)) %>% 
fill(test) 

# A tibble: 10 x 3 
# Groups: letter [3] 
    letter color test 
    <chr> <chr> <dbl> 
1  a blue  0 
2  a blue  0 
3  b <NA>  1 
4  b <NA>  1 
5  b <NA>  1 
6  b <NA>  1 
7  b <NA>  1 
8  c green  0 
9  c green  0 
10  c green  0 
+0

私はより良い例を使用すべきでした - akrunが上記の彼のコメントで述べたように。文字変数でグループ化することは自分のデータでは機能しません。混乱させて申し訳ありません。 –

関連する問題