簡體   English   中英

迭代循環后返回值 R

[英]Return values after iterating a loop R

我有兩個數據框,具有相同的變量(但來自另一個來源)。 我想以這樣的方式組合兩個數據幀,如果data中有一個值,則保留該值,否則填充來自dospert的值。

以下 function 工作:

ifelse(is.na(data$DOSPERT_01),dospert$DOSPERT_01_1,data$DOSPERT_01)

但是,由於我有大量列,我想循環執行此操作。

為此,我編寫了以下循環:

out <- list() 

for (i in 1:8){
  x <-  paste("data$DOSPERT_0",i, sep="")
  y <- paste("dospert$DOSPERT_0",i, "_01", sep="")
  z <- ifelse(is.na(x),y,x)
  out <- c(out,z)
} 

此循環打印列的名稱 ( dat$DOSPERT_030 ),但不打印相應的值。 我怎樣才能得到這些值?

數據框如下所示:

str(dospert)
 $ DOSPERT_01_1             : int  NA 5 NA NA NA 3 6 7 7 7 ...
 $ DOSPERT_02_1             : int  NA 5 NA NA NA 7 6 2 7 6 ...
 $ DOSPERT_03_1             : int  NA 1 NA NA NA 1 1 1 2 1 ...
 $ DOSPERT_04_1             : int  NA 1 NA NA NA 5 3 4 1 4 ...
 $ DOSPERT_05_1             : int  NA 1 NA NA NA 1 3 6 1 1 ...
 $ DOSPERT_06_1             : int  NA 1 NA NA NA 1 2 6 1 1 ...
 $ DOSPERT_07_1             : int  NA 6 NA NA NA 6 5 7 6 5 ...
 $ DOSPERT_08_1             : int  NA 1 NA NA NA 1 1 3 5 1 ...

str(data)
 $ DOSPERT_01: int  NA NA NA 7 NA 7 NA 7 NA NA ...
 $ DOSPERT_02: int  NA NA NA 5 NA 7 NA 7 NA NA ...
 $ DOSPERT_03: int  NA NA NA 1 NA 1 NA 1 NA NA ...
 $ DOSPERT_04: int  NA NA NA 6 NA 5 NA 1 NA NA ...
 $ DOSPERT_05: int  NA NA NA 1 NA 5 NA 4 NA NA ...
 $ DOSPERT_06: int  NA NA NA 1 NA 3 NA 3 NA NA ...
 $ DOSPERT_07: int  NA NA NA 7 NA 5 NA 6 NA NA ...
 $ DOSPERT_08: int  NA NA NA 1 NA 1 NA 1 NA NA ...

更易使用格式的樣本數據:

data <- structure(list(DOSPERT_02_1 = c(NA, 5L, NA, NA, NA, 7L, 6L, 2L, 7L, 6L), DOSPERT_03_1 = c(NA, 1L, NA, NA, NA, 1L, 1L, 1L, 2L, 1L), DOSPERT_04_1 = c(NA, 1L, NA, NA, NA, 5L, 3L, 4L, 1L, 4L), DOSPERT_05_1 = c(NA, 1L, NA, NA, NA, 1L, 3L, 6L, 1L, 1L), DOSPERT_06_1 = c(NA, 1L, NA, NA, NA, 1L, 2L, 6L, 1L, 1L), DOSPERT_07_1 = c(NA, 6L, NA, NA, NA, 6L, 5L, 7L, 6L, 5L), DOSPERT_08_1 = c(NA, 1L, NA, NA, NA, 1L, 1L, 3L, 5L, 1L)), class = "data.frame", row.names = c("1", "2", "3", "4", "5", "6", "7", "8", "9",  "10"))
dospert <- structure(list(DOSPERT_02 = c(NA, NA, NA, 5L, NA, 7L, NA, 7L, NA, NA), DOSPERT_03 = c(NA, NA, NA, 1L, NA, 1L, NA, 1L, NA, NA), DOSPERT_04 = c(NA, NA, NA, 6L, NA, 5L, NA, 1L, NA, NA), DOSPERT_05 = c(NA, NA, NA, 1L, NA, 5L, NA, 4L, NA, NA), DOSPERT_06 = c(NA, NA, NA, 1L, NA, 3L, NA, 3L, NA, NA), DOSPERT_07 = c(NA, NA, NA, 7L, NA, 5L, NA, 6L, NA, NA), DOSPERT_08 = c(NA, NA, NA, 1L, NA, 1L, NA, 1L, NA, NA)), class = "data.frame", row.names = c(NA, -10L))

由於dospert的名稱與data的名稱完全匹配(添加_1 ),這相當簡單:

all(ncol(data) == ncol(dospert) && names(data) == paste0(names(dospert), "_1"))
# [1] TRUE
data[] <- Map(data.table::fcoalesce, data, dospert)
data
#    DOSPERT_02_1 DOSPERT_03_1 DOSPERT_04_1 DOSPERT_05_1 DOSPERT_06_1 DOSPERT_07_1 DOSPERT_08_1
# 1            NA           NA           NA           NA           NA           NA           NA
# 2             5            1            1            1            1            6            1
# 3            NA           NA           NA           NA           NA           NA           NA
# 4             5            1            6            1            1            7            1
# 5            NA           NA           NA           NA           NA           NA           NA
# 6             7            1            5            1            1            6            1
# 7             6            1            3            3            2            5            1
# 8             2            1            4            6            6            7            3
# 9             7            2            1            1            1            6            5
# 10            6            1            4            1            1            5            1

如果更方便,您可以將data.table::fcoalesce替換為dplyr::coalesce ,或者編寫自己的類似合並的 function Z。

如果您很好奇, data[] <-...是因為Map返回一個list ,這意味着data將是一個list而不是data.frame 雖然我們可以包裝Map is data.frame以獲得相同的效果,但使用data[] <-替換列的內容而不是data本身的 class ,將其保留為幀。 下面的示例更好地說明了為什么使用data[...] <-無論如何可能是一個好主意。

如果相同名稱和相同順序的假設不成立,那么我們需要更加小心地比較和分配哪些列。 為了說明為什么這是真的,我將更改列的順序,省略一個,並重命名另一個,這樣我們就有: 不同的列; data中至少有一列不在dospert中; 反之亦然, dospert中至少有一列不在data中。

set.seed(42)
dospert2 <- sample(dospert[,-2])
names(dospert2)[3] <- "QUUX"
dospert2
#    DOSPERT_02 DOSPERT_07 QUUX DOSPERT_06 DOSPERT_04 DOSPERT_05
# 1          NA         NA   NA         NA         NA         NA
# 2          NA         NA   NA         NA         NA         NA
# 3          NA         NA   NA         NA         NA         NA
# 4           5          7    1          1          6          1
# 5          NA         NA   NA         NA         NA         NA
# 6           7          5    1          3          5          5
# 7          NA         NA   NA         NA         NA         NA
# 8           7          6    1          3          1          4
# 9          NA         NA   NA         NA         NA         NA
# 10         NA         NA   NA         NA         NA         NA

從這里,我們需要找到名稱與名稱匹配的位置。

dospert2_cols <- which(paste0(names(dospert2), "_1") %in% names(data))
data_cols <- na.omit(match(paste0(names(dospert2), "_1"), names(data)))
dospert2_cols
# [1] 1 2 4 5 6
data_cols
# [1] 1 6 5 3 4
# attr(,"na.action")
# [1] 3
# attr(,"class")
# [1] "omit"

從這里開始,這是對列進行子集化的問題:

data[data_cols] <- Map(data.table::fcoalesce, data[data_cols], dospert2[dospert2_cols])
data
#    DOSPERT_02_1 DOSPERT_03_1 DOSPERT_04_1 DOSPERT_05_1 DOSPERT_06_1 DOSPERT_07_1 DOSPERT_08_1
# 1            NA           NA           NA           NA           NA           NA           NA
# 2             5            1            1            1            1            6            1
# 3            NA           NA           NA           NA           NA           NA           NA
# 4             5           NA            6            1            1            7           NA
# 5            NA           NA           NA           NA           NA           NA           NA
# 6             7            1            5            1            1            6            1
# 7             6            1            3            3            2            5            1
# 8             2            1            4            6            6            7            3
# 9             7            2            1            1            1            6            5
# 10            6            1            4            1            1            5            1

由於您標記data.table ,您可以使用fcoalesce() ,它返回第一個非缺失值,並使用Map()避免詳細循環

library(data.table)

dt1 <- data.table(x = c(1, 2, NA, 3),
                  y = c(3, NA, NA, 5))
dt2 <- data.table(k = c(10, 11, 12, 13),
                  s = c(20, 21, 22, 23))

as.data.table(Map(dt1, dt2, f = data.table::fcoalesce))
#>     x  y
#> 1:  1  3
#> 2:  2 21
#> 3: 12 22
#> 4:  3  5

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM