[英]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.