我很難理解為什么下面的代碼僅rowwise
在與ifelse
. 或者更準確地說,我想我明白為什么它在這種情況下作業,但不明白為什么它不能簡單地與if_else
.
我正在做的是,我正在檢查某些行是否包含單詞“infile”或“outfile”以及它是否具有相對路徑(“..”)。如果它確實有單詞“infile/outfile”而不是相對路徑,那么它有一個絕對路徑“C:”。在這種情況下,我想用其他東西替換用戶名(這里:“test”)。
有任何想法嗎?
資料:
df <- structure(list(value = c("infile 'C:\\Users\\USER\\folder\\Data.sav'",
"infile '..\\folder\\Data.sav'", "outfile '..\\folder\\Data.sav'",
"test", "")), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA,
-5L))
user_name <- "test"
有效的代碼:
df |>
rowwise() |>
mutate(value = ifelse(str_detect(value, "infile|outfile") & !str_detect(value, "\\'\\.\\.\\\\"),
str_replace(value,
str_sub(value,
str_locate_all(value, "\\\\")[[1]][2] 1,
str_locate_all(value, "\\\\")[[1]][3] - 1),
user_name),
value)) |>
ungroup()
輸出:
# A tibble: 5 × 1
value
<chr>
1 "infile 'C:\\Users\\test\\folder\\Data.sav'"
2 "infile '..\\folder\\Data.sav'"
3 "outfile '..\\folder\\Data.sav'"
4 "test"
5 ""
不起作用的代碼:
df |>
mutate(value = if_else(str_detect(value, "infile|outfile") & !str_detect(value, "\\'\\.\\.\\\\"),
str_replace(value,
str_sub(value,
str_locate_all(value, "\\\\")[[1]][2] 1,
str_locate_all(value, "\\\\")[[1]][3] - 1),
user_name),
value))
我認為這可行,但會發出警告訊息:
Warning messages:
1: Problem while computing `value = if_else(...)`.
? empty search patterns are not supported
2: Problem while computing `value = if_else(...)`.
? empty search patterns are not supported
不起作用的代碼:
df |>
rowwise() |>
mutate(value = if_else(str_detect(value, "infile|outfile") & !str_detect(value, "\\'\\.\\.\\\\"),
str_replace(value,
str_sub(value,
str_locate_all(value, "\\\\")[[1]][2] 1,
str_locate_all(value, "\\\\")[[1]][3] - 1),
user_name),
value)) |>
ungroup()
Error in `mutate()`:
! Problem while computing `value = if_else(...)`.
? The error occurred in row 2.
Caused by error:
! Empty `pattern` not supported
uj5u.com熱心網友回復:
基本上,問題在于if_else()
評估每一行中的真偽輸出,而ifelse()
只評估使用它們的真偽運算式。
此外,如果您不使用rowwise()
,則 mutate 在每次迭代中傳遞整個字串集,df$value
然后為每行的字串的開頭和結尾回傳相同的索引。
為了除錯,我建議稍微打破計算:
df %>% rowwise() %>%
mutate(n=length(value), slen=str_length(value),
l1=str_locate_all(value,"\\\\")[[1]][2] 1,
l2=str_locate_all(value,"\\\\")[[1]][3]-1,
ssub=str_sub(value, l1, l2),
detect=str_detect(value, "infile|outfile")& !str_detect(value,"\\'\\.\\.\\\\"),
vout=if_else(detect, ssub, user_name))
# A tibble: 5 × 8
# Rowwise:
value n slen l1 l2 ssub detect vout
<chr> <int> <int> <dbl> <dbl> <chr> <lgl> <chr>
1 "infile 'C:\\Users\\USER\\folder\\Data.sav'" 1 38 18 21 "USER" TRUE USER
2 "infile '..\\folder\\Data.sav'" 1 27 19 10 "" FALSE test
3 "outfile '..\\folder\\Data.sav'" 1 28 20 11 "" FALSE test
4 "test" 1 4 NA NA NA FALSE test
5 "" 1 0 NA NA NA FALSE test
雖然沒有rowwise()
, mutate 會同時獲取 value 列中的所有字串,并且它會在每一行上找到相同的剪切位置:
df %>%
mutate(n=length(value), slen=str_length(value),
l1=str_locate_all(value,"\\\\")[[1]][2] 1,
l2=str_locate_all(value,"\\\\")[[1]][3]-1,
ssub=str_sub(value, l1, l2),
detect=str_detect(value, "infile|outfile")& !str_detect(value,"\\'\\.\\.\\\\"),
vout=if_else(detect, ssub, user_name))
# A tibble: 5 × 8
value n slen l1 l2 ssub detect vout
<chr> <int> <int> <dbl> <dbl> <chr> <lgl> <chr>
1 "infile 'C:\\Users\\USER\\folder\\Data.sav'" 5 38 18 21 "USER" TRUE USER
2 "infile '..\\folder\\Data.sav'" 5 27 18 21 "\\Dat" FALSE test
3 "outfile '..\\folder\\Data.sav'" 5 28 18 21 "r\\Da" FALSE test
4 "test" 5 4 18 21 "" FALSE test
5 "" 5 0 18 21 "" FALSE test
一旦您計算出錯誤地對字串進行子集化的位置,我認為您很幸運if_else
拋出了另一個錯誤。
uj5u.com熱心網友回復:
這是一種方法(我的替換USER
非常簡單;不確定它是否應該更通用):
df %>%
tidyr::separate(value, into = c('Type', 'Path'), sep = ' ') %>%
dplyr::mutate(
Value = dplyr::if_else(
(Type %in% c('infile', 'outfile')) & !startsWith(Path, "'.."),
stringr::str_replace(Path, 'USER', user_name),
Path
)
)
我拆分了value
列以使檢查更容易。
如果您需要用變數替換用戶名,您可以這樣做(這里使用反向參考正則運算式):
df %>%
tidyr::separate(value, into = c('Type', 'Path'), sep = ' ') %>%
dplyr::mutate(
Value = dplyr::if_else(
(Type %in% c('infile', 'outfile')) & !startsWith(Path, "'.."),
sub('^(C:\\\\Users\\\\)([[:alnum:]] )\\\\', paste0('\\1', user_name, '\\\\'), Path),
Path
)
)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/477329.html