想象一下以下資料框架:
# ID v1 v2 v3 v4
#1 H 0 0 d 0
#2 I 0 0 0 0
#3 J d 0 0 0
#4 K 0 0 0 d
#5 L 0 d 0 0
每行有一個或沒有 "d"。
對于每一行,我想將d之后的所有內容轉換為NA。希望得到的結果是:
# ID v1 v2 v3 v4
#1 H 0 0 d NA
#2 I 0 0 0 0
#3 J d NA NA NA
#4 K 0 0 0 d
#5 L 0 d NA NA
DATA
df <- data. frame(ID = LETTERS[/span>8。 12],
v1 = c(0。 0。 'd', 0。 0),
v2 = c(0。 0。 0, 0。 'd'),
v3 = c('d'。 0。 0, 0。 0),
v4 = c(0。 0。 0, 'd'/span>, 0),
stringsAsFactors = FALSE)
uj5u.com熱心網友回復:
使用cummax:
ix = df = "d"/span>
df[t(apply(ix, 1。 cummax)) & ! ix] = NA
# ID v1 v2 v3 v4
# 1 H 0 0 d <NA>
# 2 I 0 0 0 0
# 3 J d <NA> <NA> <NA>
# 4 K 0 0 0 d
# 5 L 0 d <NA> <NA>
為了提高速度,用collapse::dapply取代apply:
ix = df == "d"/span>
df[collapse:: 應用(ix, cummax。 MARGIN = 1) & ! ix] = NA
或者使用matrixStats::rowCummaxs:
ix = df = "d"/span>
df[rowCummaxs( ix) & /span> ! ix] = NA
uj5u.com熱心網友回復:
兩種替代解決方案:
# option 1
w <- which(df == "d", arr。 ind = TRUE)。
w < - w[w[,2] < ncol(df),]
reps < - ncol(df) - w[。 2]
w <- w[rep(1。 nrow(w), reps),】
w[,2]/span> < - w[。 2] unlist(sapply(reps, seq))
df[w] <- NA
#選項2
mc <- ncol(df) - max. col(df == "d", ties. 方法= "first")。
mc[mc > = (ncol(df)/span> - 1)]/span> < - 0
rr < - rep(seq_name) built_in">seq_along(mc)。 mc)
cc < - rep(ncol(df) - mc。 mc) unlist(sapply(mc, seq)[mc > 0])
df[cbind(rr。 cc)] < - NA
這兩種方法也都能得到理想的結果。
uj5u.com熱心網友回復:
我的解決版本是:
f1 < - function(x){
i1 < -其中(x == 'd') 1
cond <- length(i1) > 0 &&/span> i1 < = length(x)
if (cond){x[/span>i1: (length(x))] < - NA;x}else{x}>
}
df[-1] < - t(apply(df[-1]/span>。 1, f1))
這就得到了,
# ID v1 v2 v3 v4
#1 H 0 0 d <NA>
#2 I 0 0 0 0
#3 J d <NA> <NA> <NA>/span>
#4 K 0 0 0 d
#5 L 0 d <NA> <NA>
uj5u.com熱心網友回復:
這里有兩個基本的R單行代碼。
1) Reduce因為這一次是對整個列進行操作,而不是逐行操作,所以如果有很多行而沒有很多列的話,應該會特別快。
replace(df, TRUE。 Reduce(function(x, y) ifelse(x == "d", NA。 y), df。 acc = TRUE))
給予:
ID v1 v2 v3 v4
1 H 0 0 d <NA>
2 I 0 0 0 0
3 J d <NA> < NA> <NA>
4 K 0 0 0 d
5 L 0 d <NA> <NA>
2) read.table 這假設d的唯一出現是在由一個d組成的單元格中(問題中的例子就是這種情況)。
replace(df, df! ="d"& is. na(read.table(text=do. call(paste,df)。 comment="d"/span>。 填充=NA))。 NA)
給予:
ID v1 v2 v3 v4
1 H 0 0 d <NA>
2 I 0 0 0 0
3 J d <NA> < NA> <NA>
4 K 0 0 0 d
5 L 0 d <NA> <NA>
uj5u.com熱心網友回復:
用data.table的一些替代辦法:
library(data.table)
setDT(df)
df[。 names(df)[-1] 。 = {x <- unlist(. SD)。
if(any(x=="d")) { #如果沒有 "d"。不需要做任何事情
whd <- which(x=="d")
if(whd ! = length(x)) { # if "d" is at the end, 也沒有什么可做的
x[(whd 1)。 長度(x)] < - NA
}
}
as.list(x)} # return the line as a list so the structure is kept
. SDcols=-1。 由=1。 nrow(df)] # 你需要做一個 "按行 "的操作。
uj5u.com熱心網友回復:
另一個版本使用col和max.col:
df[/span>- 1][/span>col(df[-1]) > 最大。 col(df[/span>-1] == "d"。 "last")]/span> < - NA
df
# ID v1 v2 v3 v4
#1 H 0 0 d <NA>
#2 I 0 0 0 0
#3 J d <NA> <NA> <NA>/span>
#4 K 0 0 0 d
#5 L 0 d <NA> <NA>
uj5u.com熱心網友回復:
利用dplyr和purrr的一個選項可以是:
df %>%
mutate(pmap_dfr(across(-ID)。 ~ `[< -`(c(. .. )。 seq_along(c(。 .. )) > 其中(c(. .. ) == "d")。 NA)))
ID v1 v2 v3 v4
1 H 0 0 d <NA>
2 I 0 0 0 0
3 J d <NA> < NA> <NA>
4 K 0 0 0 d
5 L 0 d <NA> <NA>
uj5u.com熱心網友回復:
另一個dplyr解決方案
df %>%
pivot_longer(cols = starts_with("v")) %> %
group_by(ID) %> %
mutate(i = as. 邏輯的(cumsum((lag(value == "d"。 默認= FALSE)))) %> %
mutate(value = replace(value, i, NA) %> %
select(-i) %> %
pivot_wider(id_cols = ID)
uj5u.com熱心網友回復:
我認為你解決這個問題的版本是相當簡潔的。我試圖從tidyverse中想出一些東西。它是一個嵌套的across呼叫,在str_replace內使用cur_column,所以盡管是 "整潔的",我認為你的基本版本更容易閱讀。
library(dplyr)
library(stringr)
df %>%
mutate(across(v2:v4,)
~ ifelse()
rowSums(across("v1": str_replace(cur_column()/span>。 "d"。 function(y) as. numeric(y)-1)) == "d") > 0,
NA,
.x)
)
)
#> ID v1 v2 v3 v4
#> 1 H 0 0 d <NA>
#> 2 I 0 0 0 0
#> 3 J d <NA> <NA> <NA>
#> 4 K 0 0 0 d
#> 5 L 0 d <NA> <NA>
創建于2021-09-20,由reprex包(v2.0.1)
uj5u.com熱心網友回復:
base
df <- data. frame(ID = LETTERS[/span>8。 12],
v1 = c(0。 0。 'd', 0。 0),
v2 = c(0。 0。 0, 0。 'd'),
v3 = c('d'。 0。 0, 0。 0),
v4 = c(0。 0。 0, 'd'/span>, 0),
stringsAsFactors = FALSE)
df[df == "d"/span>] < - 1
l <- max. col(df[-1], ties。 方法 = "first")
tmp < - t(sapply(l。 function(x) seq(ncol(df[-1]) > x))
df[/span>-1][tmp] < - NA
df
#> ID v1 v2 v3 v4
#> 1 H 0 0 1 <NA>
#> 2 I 0 <NA> <NA> <NA>。
#> 3 J 1 <NA> <NA> <NA>
#> 4 K 0 0 0 1
#> 5 L 0 1 <NA> <NA>
創建于2021-09-20,由reprex包(v2.0.1)
uj5u.com熱心網友回復:
一種使用滯后布林值rowCums的方法。
m <- as.matrix(df)
s <- which(as. 邏輯的(matrixStats:: rowCums(m == 'd')))
m[,-1]/span>[`length< -`(s。 length(s) - nrow(m) 1)】 <。 - NA
as.data. frame(array(m, dim(df))
# V1 V2 V3 V4 V5
# 1 H 0 0 d <NA>
# 2 I 0 0 0 0
# 3 J d <NA> <NA> <NA>
# 4 K 0 0 0 d
# 5 L 0 d <NA> <NA>
uj5u.com熱心網友回復:
另一種方法是在Reduce中使用|,假設第一列是ID,沒有d。
is. na(df[/span>-1]) < -做。 call(cbind, Reduce(`|`, lapply(df[-nrow(df)】。 `==`, "d")
, accumulate = TRUE))
df
# ID v1 v2 v3 v4
#1 H 0 0 d <NA>
#2 I 0 0 0 0
#3 J d <NA> <NA> <NA>/span>
#4 K 0 0 0 d
#5 L 0 d <NA> <NA>
或者使用which和sequence。隨著從which獲得arr.ind,
i < -其中(df[c(-1。 -ncol(df)/span>)] == "d"/span>。 arr. ind = TRUE)。
n < - ncol(df) - i[/span>, 2] - 1
是。 na(df) < - cbind(rep(i[。 1], n)。 sequence(n, 2 i[/span>。 2]))
或者使用arrayInd。
i < -其中(df[c(-1。 -ncol(df)/span>)] == "d")
n < - ncol(df) - (i-1) %/% nrow(df) - 2
是。 na(df) < - arrayInd(sequence(n, i 2*nrow(df)。 nrow(df))。 dim(df))
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/326397.html
標籤:
下一篇:合并兩個資料框架
