我正在嘗試創建一些代碼來確定某個陳述是否連續三年為真。例如,該宣告是該金額需要連續三年為負數。只有當這是真的,第三行應該在一個新的列中標記為 1,否則,這些行應該標記為 0。
為了進一步詳細說明我嘗試做的事情,我創建了以下資料集:
| ID | 年 | 數量 |
|---|---|---|
| 001 | 2022 | 2 |
| 001 | 2021 | -9 |
| 001 | 2020 | -10 |
| 001 | 2019 | -16 |
| 001 | 2018 | -20 |
| 002 | 2022 | 400 |
| 002 | 2021 | 300 |
| 002 | 2020 | -200 |
| 002 | 2019 | -600 |
| 002 | 2018 | -500 |
結果應該看起來像這樣:
| ID | 年 | 數量 | 是/否 |
|---|---|---|---|
| 001 | 2022 | 2 | 0 |
| 001 | 2021 | -9 | 1 |
| 001 | 2020 | -10 | 1 |
| 001 | 2019 | -16 | 0 |
| 001 | 2018 | -20 | 0 |
| 002 | 2022 | 400 | 0 |
| 002 | 2021 | 300 | 0 |
| 002 | 2020 | -200 | 1 |
| 002 | 2019 | -600 | 0 |
| 002 | 2018 | -500 | 0 |
有人知道我怎么編碼嗎?
uj5u.com熱心網友回復:
這應該這樣做:
df <- read.table(h=T, text="ID Year Amount
001 2022 2
001 2021 -9
001 2020 -10
001 2019 -16
001 2018 -20
002 2022 400
002 2021 300
002 2020 -200
002 2019 -600
002 2018 -500")
library(tidyverse)
df %>%
group_by(ID) %>%
mutate(YN = rev(diff(c(0,0,0, cumsum(rev(Amount)<0)), 3) == 3)) %>%
ungroup()
#> # A tibble: 10 × 4
#> ID Year Amount YN
#> <int> <int> <int> <lgl>
#> 1 1 2022 2 FALSE
#> 2 1 2021 -9 TRUE
#> 3 1 2020 -10 TRUE
#> 4 1 2019 -16 FALSE
#> 5 1 2018 -20 FALSE
#> 6 2 2022 400 FALSE
#> 7 2 2021 300 FALSE
#> 8 2 2020 -200 TRUE
#> 9 2 2019 -600 FALSE
#> 10 2 2018 -500 FALSE
由reprex 包于 2022-04-21 創建(v2.0.1)
在基礎 R 中:
df$YN <- ave(df$Amount, df$ID, FUN = function(x) rev(diff(c(0,0,0, cumsum(rev(x)<0)), 3) == 3)) == 1
這是一個演練:
df %>%
arrange(ID, Year) %>%
group_by(ID) %>%
mutate(
cond = Amount < 0,
cumsum = cumsum(cond),
diff = diff(c(0,0,0, cumsum), 3),
YN = diff == 3) # %>% arrange(ID, desc(Year)) # to put back in original shape
#> # A tibble: 10 × 7
#> # Groups: ID [2]
#> ID Year Amount cond cumsum diff YN
#> <int> <int> <int> <lgl> <int> <dbl> <lgl>
#> 1 1 2018 -20 TRUE 1 1 FALSE
#> 2 1 2019 -16 TRUE 2 2 FALSE
#> 3 1 2020 -10 TRUE 3 3 TRUE
#> 4 1 2021 -9 TRUE 4 3 TRUE
#> 5 1 2022 2 FALSE 4 2 FALSE
#> 6 2 2018 -500 TRUE 1 1 FALSE
#> 7 2 2019 -600 TRUE 2 2 FALSE
#> 8 2 2020 -200 TRUE 3 3 TRUE
#> 9 2 2021 300 FALSE 3 2 FALSE
#> 10 2 2022 400 FALSE 3 1 FALSE
還有一個更容易閱讀的解決方案,不能推廣到大跨度:
library(tidyverse)
df %>%
group_by(ID) %>%
mutate(YN = (Amount < 0) lead(Amount < 0, default = 0) lead(Amount < 0, 2, default = 0) == 3) %>%
ungroup()
uj5u.com熱心網友回復:
使用資料集
df <- data.frame(id = c(rep(1,5,),rep(2,5)), year = rep(seq(2022,2018),2), amount = c(2,-9,-10,-16,-20,400,300,-200,-600,-500))
sapply可以使用一個函式:
df$test <- ifelse(sapply(seq(1,nrow(df)), function(x) all(subset(df, df$id == df$id[x] & df$year %in% seq(df$year[x]-2,df$year[x]))$amount < 0) & nrow(subset(df, df$id == df$id[x] & df$year %in% seq(df$year[x]-2,df$year[x]))) > 2),1,0)
這給出了:
df
id year amount test
1 1 2022 2 0
2 1 2021 -9 1
3 1 2020 -10 1
4 1 2019 -16 0
5 1 2018 -20 0
6 2 2022 400 0
7 2 2021 300 0
8 2 2020 -200 1
9 2 2019 -600 0
10 2 2018 -500 0
分解:
ifelse將 TRUE/FALSE 從 SAPPLY 更改為 1/0
sapply每行迭代
all測驗條件是否適用于子集中的所有值
subset選擇最近三年和正確的身份證
$amount < 0測驗條件
uj5u.com熱心網友回復:
您可以使用 data.table 包。
library(data.table)
setDT(df)
df[order(Year), YN := match(Reduce(` `, shift(Amount<0, 0:2)), 3, 0), ID]
# ID Year Amount YN
# 1: 1 2022 2 0
# 2: 1 2021 -9 1
# 3: 1 2020 -10 1
# 4: 1 2019 -16 0
# 5: 1 2018 -20 0
# 6: 2 2022 400 0
# 7: 2 2021 300 0
# 8: 2 2020 -200 1
# 9: 2 2019 -600 0
# 10: 2 2018 -500 0
資料
df = structure(list(ID = c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2),
Year = c(2022, 2021, 2020, 2019, 2018, 2022, 2021, 2020, 2019, 2018),
Amount = c(2, -9, -10, -16, -20, 400, 300, -200, -600, -500)),
row.names = c(NA, -10L),
class = "data.frame")
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/460967.html
標籤:r
