[英]Ifelse across multiple columns matching on similar attributes
我需要創建一個名為 dum 的二進制變量(可能使用 ifelse 語句)匹配列名的數量。
ifelse f[number] %in% c(4:6) & l[number]==1, 1, 否則 0
f1<-c(3,2,1,6,5)
f2<-c(4,1,5,NA,NA)
f3<-c(5,3,4,NA,NA)
f4<-c(1,2,4,NA,NA)
l1<-c(1,0,1,0,0)
l2<-c(1,1,1,NA,NA)
l3<-c(1,0,0,NA,NA)
l4<-c(0,0,0,NA,NA)
mydata<-data.frame(f1,f2,f3,f4,l1,l2,l3,l4)
如果 f1 包含 4、5、6 之間的值並且 l1 包含 1 的值,或者 f2 包含 4、5、6 之間的值並且 l2 包含 1 的值,則 dum 為 1,依此類推。
本質上,預期的 output 應該是
f1 f2 f3 f4 l1 l2 l3 l4 dum
1 3 4 5 1 1 1 1 0 1
2 2 1 3 2 0 1 0 0 0
3 1 5 4 4 1 1 0 0 1
4 6 NA NA NA 0 NA NA NA 0
5 5 NA NA NA 0 NA NA NA 0
我只能想到做很長的路,比如
mutate(dum=ifelse(f1 %in% c(4:6 & l1==1, 1,
ifelse(f2 %in% c(4:6) & l2==1, 1,
ifelse(f3 %in% c(4:6) & l3==1, 1,
ifelse(f4 %in% c(4:6) & l4==1, 1, 0))))
但這很麻煩,因為實際數據的列數要多得多,並且最多可以達到 f20 和 l20 go。
有沒有更有效的方法來做到這一點?
這是一個建議。 這也不是很清楚。 假設您想要一個帶有dum
的列,它指示任何列中該行的列名中的數字的存在:
library(dplyr)
library(readr)
mydata %>%
mutate(across(f1:l4, ~case_when(. == parse_number(cur_column()) ~ 1,
TRUE ~ 0), .names = 'new_{col}')) %>%
mutate(sumNew = rowSums(.[9:16])) %>%
mutate(dum = ifelse(sumNew >=1, 1, 0)) %>%
select(1:8, dum)
f1 f2 f3 f4 l1 l2 l3 l4 dum
1 3 4 5 1 1 1 1 0 1
2 2 1 3 2 0 1 0 0 1
3 1 5 4 4 1 1 0 0 1
4 6 NA NA NA 0 NA NA NA 0
5 5 NA NA NA 0 NA NA NA 0
這是一個across
“f”列的選項across
使用第一個條件, across
應用第二個條件的情況下循環“l”列,將它們與&
連接在一起以返回邏輯矩陣,獲得行式總和列( TRUE
-> 1 和FALSE
-> 0),檢查該總和是否大於 0(即該行中是否有任何 TRUE),並使用+
或as.integer
將邏輯強制轉換為二進制
library(dplyr)
mydata %>%
mutate(dum = +(rowSums(across(starts_with('f'), ~.x %in% 4:6) &
across(starts_with('l'), ~ .x %in% 1)) > 0))
f1 f2 f3 f4 l1 l2 l3 l4 dum
1 3 4 5 1 1 1 1 0 1
2 2 1 3 2 0 1 0 0 0
3 1 5 4 4 1 1 0 0 1
4 6 NA NA NA 0 NA NA NA 0
5 5 NA NA NA 0 NA NA NA 0
我們也可以使用base R
mydata$dum <- +(Reduce(`|`, Map(function(x, y) x %in% 4:6 &
y %in% 1, mydata[startsWith(names(mydata), "f")],
mydata[startsWith(names(mydata), "l")])))
這是一種將兩個mapply
相乘的方法,用grep
標識的列,然后計算rowSums > 0
。 如果你設置na.rm=F
你可以在相應的行中得到NA
s。
as.integer(rowSums(mapply(`%in%`, mydata[grep('^f', names(mydata))], list(4:6))*
mapply(`==`, mydata[grep('^l', names(mydata))], 1), na.rm=T) > 0)
# [1] 1 0 1 0 0
如果f*
和l*
都不連續,則使用sort(grep(., value=T))
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.