Большинство ответов здесь затрагивают этот вопрос в очень сухих технических терминах. Я хотел бы остановиться на этом в терминах, которые могут понять обычные люди.
Представьте, что вы пытаетесь нарезать пиццу. У вас есть роботизированный резак для пиццы, который может разрезать кусочки пиццы ровно пополам. Он может вдвое сократить целую пиццу, или он может сократить вдвое существующий кусочек, но в любом случае половина всегда точна.
У этого резца пиццы очень хорошие движения, и если вы начнете с целой пиццы, затем уменьшите вдвое и продолжайте вдвое уменьшать наименьший срез каждый раз, вы можете сделать половину 53 раза , прежде чем срез слишком мал для даже его высокоточных способностей. В этот момент вы уже не можете вдвое уменьшить этот тонкий срез, но должны либо включать, либо исключать его, как есть.
Теперь, как бы вы отделили все срезы таким образом, чтобы добавить один (0,1) или одну пятую (0,2) пиццы? На самом деле подумайте об этом и попробуйте разобраться. Вы даже можете попытаться использовать настоящую пиццу, если у вас есть мифическая пресса для резки пиццы под рукой. : -)
Большинство опытных программистов, конечно же, знают реальный ответ, который заключается в том, что нет возможности собрать кусок точной десятой или пятой пиццы используя эти срезы, независимо от того, насколько мелко вы их нарезаете. Вы можете сделать довольно хорошее приближение, и если вы добавите аппроксимацию 0,1 с аппроксимацией 0,2, вы получите довольно хорошее приближение 0,3, но это все равно именно это, приближение.
Для двойного -оценки (это точность, которая позволяет вам вдвое сократить вашу пиццу 53 раза), цифры сразу меньше и больше 0,1 - 0.09999999999999999167332731531132594682276248931884765625 и 0,1000000000000000055511151231257827021181583404541015625. Последнее немного ближе к 0,1, чем первое, поэтому числовой синтаксический анализатор, учитывая ввод 0,1, благоприятствует последнему.
(Разница между этими двумя числами - это «самый маленький срез», который мы должны решить либо включить, что вводит восходящее смещение, либо исключить, что приводит к смещению вниз. Техническим термином для этого наименьшего среза является ulp .)
В случай 0,2, числа все одинаковы, просто увеличиваются в 2 раза. Опять же, мы одобряем значение, которое немного выше 0,2.
Обратите внимание, что в обоих случаях приближения для 0,1 и 0.2 имеют небольшое смещение вверх. Если мы добавим достаточно этих предубеждений, они будут толкать число дальше и дальше от того, что мы хотим, а на самом деле, в случае 0,1 + 0,2, смещение достаточно велико, чтобы получившееся число больше не было самым близким числом до 0,3.
в частности, 0,1 + 0,2 действительно 0.1000000000000000055511151231257827021181583404541015625 + 0.200000000000000011102230246251565404236316680908203125 = 0.3000000000000000444089209850062616169452667236328125, тогда как число ближе к 0,3 фактически 0,299999999999999988897769753748434595763683319091796875.
П.С. Некоторые языки программирования также предоставляют резаки для пиццы, которые могут разделять фрагменты на точные десятки . Хотя такие резаки для пиццы необычны, если у вас есть доступ к одному, вы должны использовать его, когда важно получить ровно одну десятую или одну пятую части среза.
( Первоначально опубликовано на Quora.)
ч>
Я хочу использовать R, а не предварительно обрабатывать данные, поскольку это облегчает пересмотр данных. Следуя предложению Шейна использовать gsub
, я думаю, что это примерно так же аккуратно, как я могу:
x <- read.csv("file.csv",header=TRUE,colClasses="character")
col2cvt <- 15:41
x[,col2cvt] <- lapply(x[,col2cvt],function(x){as.numeric(gsub(",", "", x))})
Это не так сложно, попробуйте это: y & lt; - as.numeric (gsub (",", "", as.character (y))), и если это только один из столбцов, вы можете подмножить его с y $ 2, как показано y $ 2 & lt; - as.numeric (gsub (",", "", as.character (y $ 2)))
Очень удобный способ readr::read_delim
-семейство. Взяв пример отсюда: Импортируя csv с несколькими разделителями в R , вы можете сделать это следующим образом:
txt <- 'OBJECTID,District_N,ZONE_CODE,COUNT,AREA,SUM
1,Bagamoyo,1,"136,227","8,514,187,500.000000000000000","352,678.813105723350000"
2,Bariadi,2,"88,350","5,521,875,000.000000000000000","526,307.288878142830000"
3,Chunya,3,"483,059","30,191,187,500.000000000000000","352,444.699742995200000"'
require(readr)
read_csv(txt) # = read_delim(txt, delim = ",")
. Это приводит к ожидаемому результату:
# A tibble: 3 × 6
OBJECTID District_N ZONE_CODE COUNT AREA SUM
<int> <chr> <int> <dbl> <dbl> <dbl>
1 1 Bagamoyo 1 136227 8514187500 352678.8
2 2 Bariadi 2 88350 5521875000 526307.3
3 3 Chunya 3 483059 30191187500 352444.7
Не знаете, как правильно интерпретировать read.csv
, но вы можете использовать gsub
для замены ","
на ""
, а затем преобразовать строку в numeric
с помощью as.numeric
:
y <- c("1,200","20,000","100","12,111")
as.numeric(gsub(",", "", y))
# [1] 1200 20000 100 12111
Это было , также ранее упоминавшееся в R-Help (и в Q2 здесь ).
Кроме того, обрабатывать файл, например, с помощью sed
в unix.
Используя функцию read_delim, которая является частью библиотеки readr, вы можете указать дополнительный параметр:
locale = locale(decimal_mark = ",")
read_delim("filetoread.csv", ';", locale = locale(decimal_mark = ","))
* Точка с запятой во второй строке означает, что read_delim будет считывать значения с разделителями с запятой csv.
Это поможет прочитать все числа с запятой как правильные числа.
С уважением
Mateusz Kania
Этот вопрос несколько лет, но я наткнулся на него, а это значит, что другие будут.
Библиотека / пакет readr
имеет некоторые полезные функции. Один из них - хороший способ интерпретировать «грязные» столбцы, такие как.
library(readr)
read_csv("numbers\n800\n\"1,800\"\n\"3500\"\n6.5",
col_types = list(col_numeric())
)
Это дает
Источник: локальный фрейм данных [4 x 1]
numbers
(dbl)
1 800.0
2 1800.0
3 3500.0
4 6.5
Важным моментом при чтении файлов является либо предварительная обработка, как комментарий выше относительно sed
, либо вы должны обрабатывать во время чтения. Часто, если вы пытаетесь исправить ситуацию после факта, есть некоторые опасные предположения, которые трудно найти. (Вот почему плоские файлы так злы в первую очередь.)
Например, если бы я не помечен col_types
, я бы получил следующее:
> read_csv("numbers\n800\n\"1,800\"\n\"3500\"\n6.5")
Source: local data frame [4 x 1]
numbers
(chr)
1 800
2 1,800
3 3500
4 6.5
(Обратите внимание, что теперь это chr
(character
) вместо numeric
.)
Или, что более опасно, если бы оно было достаточно длинным, и большинство ранних элементов не содержало запятые:
> set.seed(1)
> tmp <- as.character(sample(c(1:10), 100, replace=TRUE))
> tmp <- c(tmp, "1,003")
> tmp <- paste(tmp, collapse="\"\n\"")
(так, что последние несколько элементов выглядят так:)
\"5\"\n\"9\"\n\"7\"\n\"1,003"
Тогда вы найдете проблемы с чтением этой запятой вообще!
> tail(read_csv(tmp))
Source: local data frame [6 x 1]
3"
(dbl)
1 8.000
2 5.000
3 5.000
4 9.000
5 7.000
6 1.003
Warning message:
1 problems parsing literal data. See problems(...) for more details.
Другое решение:
y <- c("1,200","20,000","100","12,111")
as.numeric(unlist(lapply( strsplit(y,","),paste, collapse="")))
Это будет значительно медленнее, чем gsub
.
dplyr
с использованием mutate_each
и труб говорит, что у вас есть следующее:
> dft
Source: local data frame [11 x 5]
Bureau.Name Account.Code X2014 X2015 X2016
1 Senate 110 158,000 211,000 186,000
2 Senate 115 0 0 0
3 Senate 123 15,000 71,000 21,000
4 Senate 126 6,000 14,000 8,000
5 Senate 127 110,000 234,000 134,000
6 Senate 128 120,000 159,000 134,000
7 Senate 129 0 0 0
8 Senate 130 368,000 465,000 441,000
9 Senate 132 0 0 0
10 Senate 140 0 0 0
11 Senate 140 0 0 0
и хотите удалить запятые из переменных года X2014-X2016, и преобразовать их в числовые. также, скажем, X2014-X2016 читаются как факторы (по умолчанию)
dft %>%
mutate_each(funs(as.character(.)), X2014:X2016) %>%
mutate_each(funs(gsub(",", "", .)), X2014:X2016) %>%
mutate_each(funs(as.numeric(.)), X2014:X2016)
mutate_each
применяет функцию (ы) внутри funs
к указанным столбцам
I последовательно выполнял одну функцию за раз (если вы используете несколько функций внутри funs
, тогда вы создаете дополнительные ненужные столбцы)
Я думаю, что предварительная обработка - это путь. Вы можете использовать Notepad ++ , у которого есть опция замены регулярного выражения.
Например, если ваш файл был таким:
"1,234","123","1,234"
"234","123","1,234"
123,456,789
Тогда вы могли бы используйте регулярное выражение "([0-9]+),([0-9]+)"
и замените его на \1\2
1234,"123",1234
"234","123",1234
123,456,789
. Затем вы можете использовать x <- read.csv(file="x.csv",header=FALSE)
для чтения файла.
Если номер разделен символом "." и десятичные знаки «,» (1.200.000,00) при вызове gsub
вы должны set fixed=TRUE as.numeric(gsub(".","",y,fixed=TRUE))