簡體   English   中英

Ifelse 跨多個列匹配相似的屬性

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

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