Вот tidyverse
подход к вашей проблеме, возможно, очень подробный. Некоторые пояснения:
1) Первый блок mutate()
округляет оба столбца Delta
до одной значащей цифры и преобразует ее в символ; это сохраняет длину.
2) Второй блок mutate()
округляет «обычные» столбцы x
и y
, чтобы они имели ту же длину, что и столбцы Delta
. - 2L
позволяет избежать ложного округления на основе числа перед .
и самого .
в столбцах Delta
.
3) Третий блок mutate()
сначала обрабатывает две "необычные" ситуации: первый блок if_else()
обрабатывает ситуации, когда округленное число y
не имеет .
и цифр, а значение Delta.y
имеет. Второй if_else()
заботится о ситуациях, когда последней цифрой в процессе округления является 0
, которая R
отбрасывается при округлении. Обе меры повторяются для столбца x
.
4) Четвертый блок mutate()
добавляет пробелы в конце значений в столбцах x
и y
, чтобы убедиться, что номера ошибок выровнены.
5) Команды unite()
и mutate()
в конце объединяют столбцы и добавляют скобки для второго числа.
library("tidyverse")
library("knitr")
df %>%
mutate(Delta.x = signif(Delta.x, digits = 1L),
Delta.x = as.character(Delta.x),
Delta.y = signif(Delta.y, digits = 1L),
Delta.y = as.character(Delta.y)) %>%
mutate(x = round(x, digits = str_count(Delta.x) - 2L),
x = as.character(x),
y = round(y, digits = str_count(Delta.y) - 2L),
y = as.character(y)) %>%
mutate(y = if_else(condition = str_count(y, "\\.") == 0,
true = str_c(y, str_dup("0", str_count(Delta.y) - str_count(y) - 1L), sep = "."),
false = y),
y = if_else(condition = str_count(Delta.y) - str_count(y) != 0,
true = str_c(y, str_dup("0", times = str_count(Delta.y) - str_count(y))),
false = y),
x = if_else(condition = str_count(x, "\\.") == 0,
true = str_c(x, str_dup("0", str_count(Delta.x) - str_count(x) - 1L), sep = "."),
false = x),
x = if_else(condition = str_count(Delta.x) - str_count(x) != 0,
true = str_c(x, str_dup("0", times = str_count(Delta.x) - str_count(x))),
false = x)) %>%
mutate(x = if_else(condition = str_count(x) < max(str_count(x)),
true = str_c(x, str_dup(" ", times = max(str_count(x)) - str_count(x))),
false = x),
y = if_else(condition = str_count(y) < max(str_count(y)),
true = str_c(y, str_dup(" ", times = max(str_count(y)) - str_count(y))),
false = y)) %>%
unite(x, x, Delta.x, sep = " (") %>%
unite(y, y, Delta.y, sep = " (") %>%
mutate(x = str_c(x, ")"),
y = str_c(y, ")")) %>%
kable()
|x |y |
|:-----------|:-------------|
|1.0 (0.1) |0.20 (0.01) |
|0.12 (0.07) |0.8 (0.1) |
|0.71 (0.03) |0.18 (0.09) |
|0.63 (0.02) |0.805 (0.003) |
|0.27 (0.09) |0.106 (0.008) |
Кроме того, вы можете установить глобальное options(scipen = 999)
(или любое другое большое число), чтобы избежать научного представления чисел, например. 2e-5
(что в случае вашего kable
должно выглядеть как 0.00002
).
EDIT: обновлены и уточнены некоторые команды.
ОБНОВЛЕНИЕ (Javi_VM)
Я просто превратил его в функцию. Вы можете указать либо 2 вектора, либо 1 data.frame с двумя столбцами. Он по-прежнему не поддерживает экспоненциальное представление (например, 1,05 10 ^ 9), но для начала все в порядке.
scinumber <- function(df=NULL, x, Delta.x){
if (is.null(df)) {
df <- data.frame(
x = x,
Delta.x = Delta.x
)
} else {
colnames(df)[colnames(df)==x] <- "x"
colnames(df)[colnames(df)==Delta.x] <- "Delta.x"
}
require(tidyverse)
options(scipen = 999)
output <-
df %>%
mutate(Delta.x = signif(Delta.x, digits = 1L),
Delta.x = as.character(Delta.x)) %>%
mutate(x = round(x, digits = str_count(Delta.x) - 2L),
x = as.character(x)
) %>%
mutate(x = if_else(condition = str_count(x, "\\.") == 0,
true = str_c(x, str_dup("0", str_count(Delta.x) - str_count(x) - 1L), sep = "."),
false = x),
x = if_else(condition = str_count(Delta.x) - str_count(x) != 0,
true = str_c(x, str_dup("0", times = str_count(Delta.x) - str_count(x))),
false = x)) %>%
mutate(x = if_else(condition = str_count(x) < max(str_count(x)),
true = str_c(x, str_dup(" ", times = max(str_count(x)) - str_count(x))),
false = x)) %>%
unite(x, x, Delta.x, sep = " (") %>%
mutate(x = str_c(x, ")"))
return(output)
}
person
Supertasty
schedule
12.03.2018
sprintf
:df.print<-with(df, data.frame( x=paste(sprintf("%.2f", x), "±", sprintf("%.2f", Delta.x)), y=paste(sprintf("%.2f", y), "±", sprintf("%.2f", Delta.y)) ))
- person JasonAizkalns   schedule 12.03.2018"%.2f"
,"%.3f"
) автоматически на основе значений Delta.x или Delta.y? - person Javi_VM   schedule 12.03.2018