I have
df = data.frame(Col1 = c( NA, 1," ", 2345.768,"hi","", NA, 3.4, "44.99"))
and want to format specific values, and created a udf
format_it = function(y, n_decimals, dash_type, suffix = ""){
if(is.na(y)) return(dash_type)
if(nchar(gsub(" ", "", y))==0) return(y)
has_letter = grep("[A-z]+", y)
if(is_empty(has_letter)== TRUE) {
return(paste0(format(round(as.numeric(y), n_decimals), nsmall=n_decimals, big.mark = ","),suffix))
}
if(has_letter == 1){
return(y)
} else{
x = as.numeric(y)
ifelse(is.na(x),
dash_type,
paste0(format(round(as.numeric(x), n_decimals), nsmall=n_decimals, big.mark = ","),suffix))}
}
I tested each value individually, ie format_it(df$Col1[1],1,"-")
, and each one worked ok
but, when I set up a set_formatter
in flextable,
df %>%
flextable() %>%
set_formatter(Col1 = function(x) format_it(x,1,"-"))
I hoped the results would be correct, but received the wrong results,
with the message: the condition has length > 1 and only the first element will be used
I tried updating to include Vectorize
, but received the same error
Any suggestions?
I would like to see
I'm a little confused on your function, but a fresh code approach to recreating your table (based on your function) in a reproducible way is below, which produces your desired output. It first replaces any NA
values in the original data with "-", then checks for all non-numeric values (ie, "hi") using grepl
and keeps those the same, then standardizes the significant digits in the numeric values with sprintf
. This approach was within the dplyr
"world" using mutate()
and case_when()
and did not use a user-defined function.
df %>%
mutate(Col1 = case_when(
is.na(Col1) ~ "-",
!grepl("[^A-Za-z]", Col1) ~ Col1,
grepl(".", Col1) ~ sprintf("%.1f", as.numeric(Col1)),
)) %>%
flextable::flextable()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.