Bazı sayılar binlik ayırıcı olarak virgül içerdiğinde veriler nasıl okunur?


117

Bazı sayısal değerlerin virgülle bin ayırıcısı olarak dizeler olarak ifade edildiği bir csv dosyam var, örneğin "1,513"bunun yerine 1513. Verileri R'ye okumanın en basit yolu nedir?

Kullanabilirim read.csv(..., colClasses="character"), ancak o zaman bu sütunları sayısal hale getirmeden önce ilgili öğelerdeki virgülleri çıkarmam gerekiyor ve bunu yapmanın düzgün bir yolunu bulamıyorum.

Yanıtlar:


141

Emin değilim yaklaşık nasıl olması read.csvgerektiği gibi yorumlamak, ancak kullanabilirsiniz gsubyerine ","sahip ""ve sonra dize dönüştürmek numerickullanarak as.numeric:

y <- c("1,200","20,000","100","12,111")
as.numeric(gsub(",", "", y))
# [1]  1200 20000 100 12111

Bu aynı zamanda daha önce R-Help'te (ve burada 2. Çeyrekte ) yanıtlandı .

Alternatif olarak, dosyayı örneğin sedunix ile önceden işleyebilirsiniz .


60

Bu dönüşümü sizin için yarı otomatik olarak read.table veya read.csv'ye yaptırabilirsiniz. Önce yeni bir sınıf tanımı oluşturun, ardından bir dönüştürme işlevi oluşturun ve bunu setAs işlevini kullanarak bir "as" yöntemi olarak ayarlayın:

setClass("num.with.commas")
setAs("character", "num.with.commas", 
        function(from) as.numeric(gsub(",", "", from) ) )

Ardından read.csv'yi şu şekilde çalıştırın:

DF <- read.csv('your.file.here', 
   colClasses=c('num.with.commas','factor','character','numeric','num.with.commas'))

3
Bu çok güzel bir numara. İçe aktarmada dönüşüm için kullanılabilir (örneğin, E / N değerlerini kullanarak mantıksal vektöre dönüştürmek setAs("character", "logical.Y.N", function(from) c(Y=TRUE,N=FALSE)[from] )).
Marek

1
Benzer problemde aynı numara kullanımı . Ve eklemek için: biri setClass("num.with.commas")veya suppresMessage(setAs(.....))eksik sınıf mesajından kaçınmak için kullanılabilir .
Marek

Merhaba Greg, bu kullanışlı işlevi paylaştığınız için teşekkürler. Yürütme sırasında şu uyarıyı alıyorum: "karakter", "num.with.commas" 'imzalı' zorlama 'yönteminde: "num.with.commas" sınıfı için tanım yok Sorunun burada ne olduğu hakkında herhangi bir fikriniz var, Kelime kelime kodunuz bende mi?
TheGoat

Benzer sorun bağlantısını kontrol ettim ve sınıfı belirlemem gerektiğini gördüm! Güzel numara için teşekkürler.
TheGoat

17

Verileri önceden işlemek yerine R kullanmak istiyorum çünkü veriler revize edildiğinde işleri kolaylaştırıyor. Shane'in kullanma önerisini takiben gsub, bunun elimden geldiği kadar düzgün olduğunu düşünüyorum:

x <- read.csv("file.csv",header=TRUE,colClasses="character")
col2cvt <- 15:41
x[,col2cvt] <- lapply(x[,col2cvt],function(x){as.numeric(gsub(",", "", x))})

ColClasses = "char" tüm sütunları char olmaya zorlamaz, bu durumda 15:41 dışındaki diğerleri de char olur? Belki read.csv () 'nin karar vermesine izin vermek ve sonra sütun 15:41 içindekileri dönüştürmek size' daha fazla 'sayısal sütun getirebilir.
Dirk Eddelbuettel

Evet, ama sorumun da belirttiği gibi, diğer tüm sütunlar karakterdir. Onun yerine as.is = TRUE kullanabilirim ki bu daha genel olacaktır. Ancak read.csv () 'nin varsayılan bağımsız değişkenleri kullanarak karar vermesine izin vermek yararlı değildir çünkü karakter gibi görünen her şeyi, sayısal sütunlar için sorunlara neden olan bir faktöre dönüştürür, çünkü o zaman as.numeric () kullanılarak düzgün şekilde dönüştürülmezler. .
Rob Hyndman

Okunan tablodaki dec = argümanını "." Olarak ayarlamayı düşünmelisiniz. Bu, read.csv2 için varsayılandır ancak virgül, read.csv () 'ye fiziksel olarak bağlanmıştır.
IRTFM

15

Bu soru birkaç yaşında, ama ben ona rastladım, bu da belki başkalarının isteyeceği anlamına geliyor.

readrKütüphane / paket o güzel bazı özelliklere sahiptir. Bunlardan biri, bunun gibi "dağınık" yazıları yorumlamanın güzel bir yoludur.

library(readr)
read_csv("numbers\n800\n\"1,800\"\n\"3500\"\n6.5",
          col_types = list(col_numeric())
        )

Bu verir

Kaynak: yerel veri çerçevesi [4 x 1]

  numbers
    (dbl)
1   800.0
2  1800.0
3  3500.0
4     6.5

Dosyalarda okurken önemli bir nokta: ya yukarıdaki yorumda olduğu gibi ön işlem yapmalısınız sedya da okurken işlem yapmalısınız . Genellikle, olaydan sonra bir şeyleri düzeltmeye çalışırsanız, bulunması zor olan bazı tehlikeli varsayımlar yapılır. (Bu yüzden düz dosyalar ilk etapta çok kötüdür.)

Örneğin, işaretlemeseydim col_types, şunu alırdım:

> 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

(Artık a yerine a chr( character) olduğuna dikkat edin numeric.)

Ya da daha tehlikeli bir şekilde, yeterince uzun olsaydı ve ilk öğelerin çoğu virgül içermiyorsa:

> set.seed(1)
> tmp <- as.character(sample(c(1:10), 100, replace=TRUE))
> tmp <- c(tmp, "1,003")
> tmp <- paste(tmp, collapse="\"\n\"")

(öyle ki son birkaç öğe şöyle görünür :)

\"5\"\n\"9\"\n\"7\"\n\"1,003"

O zaman o virgülü okumakta zorlanacaksınız!

> 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. 

7

ve borular dplyrkullanan bir çözümmutate_all

aşağıdakilere sahip olduğunuzu söyleyin:

> 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

ve X2014-X2016 yıl değişkenlerinden virgül kaldırmak ve bunları sayısal hale dönüştürmek istiyorsanız. ayrıca, diyelim ki X2014-X2016 faktör olarak okundu (varsayılan)

dft %>%
    mutate_all(funs(as.character(.)), X2014:X2016) %>%
    mutate_all(funs(gsub(",", "", .)), X2014:X2016) %>%
    mutate_all(funs(as.numeric(.)), X2014:X2016)

mutate_alliçindeki fonksiyon (lar) ı funsbelirtilen sütunlara uygular

Sırayla yaptım, her seferinde bir işlev (içinde birden fazla işlev kullanırsanız funs, ek, gereksiz sütunlar oluşturursunuz)


3
mutate_eachkullanımdan kaldırıldı. Cevabınızı mutate_atveya benzeri bir şekilde güncellemek ister misiniz ?
T_T

6

R'de "Ön işlem":

lines <- "www, rrr, 1,234, ttt \n rrr,zzz, 1,234,567,987, rrr"

Kullanabilir readLinesa üzerinde textConnection. Ardından, yalnızca rakamlar arasındaki virgülleri kaldırın:

gsub("([0-9]+)\\,([0-9])", "\\1\\2", lines)

## [1] "www, rrr, 1234, ttt \n rrr,zzz, 1234567987, rrr"

Virgüllerin ondalık ayırıcılar olarak read.csv2 (otomatik olarak) veya read.table ('dec' parametresinin ayarlanmasıyla) ile işlenebileceğini bilmek ancak bu soruyla doğrudan alakalı değildir.

Düzenleme: Daha sonra yeni bir sınıf tasarlayarak colClass'ların nasıl kullanılacağını keşfettim. Görmek:

Sayısal sınıf olarak R'ye 1000 ayırıcılı df nasıl yüklenir?


Teşekkürler, bu iyi bir göstericiydi, ancak birkaç ondalık işaret içeren basamaklar için işe yaramıyor, örneğin 1.234.567.89 - bir Google e-tablosunu R'ye aktarmak için bu sorunu çözmek için gerekli, basit bir bilgi için stackoverflow.com/a/30020171/3096626'ya bakın birden çok ondalık işaret için işi yapan işlev
flexponsive

4

Numara "" ile ayrılıyorsa. ve "," (1.200.000,00) ile ondalık basmanız gsubgerekirset fixed=TRUE as.numeric(gsub(".","",y,fixed=TRUE))


3

Çok uygun bir yol- readr::read_delimailedir. Örneği buradan ele alalım: Birden çok ayırıcı ile csv'yi R'ye içe aktarmak , aşağıdaki gibi yapabilirsiniz:

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 = ",")

Beklenen sonuçla sonuçlanan:

# 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

3

Readr kitaplığının parçası olan read_delim işlevini kullanarak ek parametreler belirtebilirsiniz:

locale = locale(decimal_mark = ",")

read_delim("filetoread.csv", ';", locale = locale(decimal_mark = ","))

* İkinci satırdaki noktalı virgül, read_delim'in csv noktalı virgülle ayrılmış değerleri okuyacağı anlamına gelir.

Bu, tüm sayıları virgülle doğru sayı olarak okumaya yardımcı olacaktır.

Saygılarımızla

Mateusz Kania


3

Ayrıca kullanabiliriz readr::parse_number, sütunlar yine de karakter olmalıdır. Birden fazla sütun için uygulamak istersek, şunu kullanarak sütunlar arasında döngü yapabilirizlapply

df[2:3] <- lapply(df[2:3], readr::parse_number)
df

#  a        b        c
#1 a    12234       12
#2 b      123  1234123
#3 c     1234     1234
#4 d 13456234    15342
#5 e    12312 12334512

Veya belirli değişkenlere uygulamak için ' mutate_atden dplyrkullanın.

library(dplyr)
df %>% mutate_at(2:3, readr::parse_number)
#Or
df %>% mutate_at(vars(b:c), readr::parse_number)

veri

df <- data.frame(a = letters[1:5], 
                 b = c("12,234", "123", "1,234", "13,456,234", "123,12"),
                 c = c("12", "1,234,123","1234", "15,342", "123,345,12"), 
                 stringsAsFactors = FALSE)

1

Bence ön işleme, gidilecek yol. Normal ifade değiştirme seçeneği olan Notepad ++ ' ı kullanabilirsiniz .

Örneğin, dosyanız şöyle olsaydı:

"1,234","123","1,234"
"234","123","1,234"
123,456,789

Daha sonra normal ifadeyi kullanabilir "([0-9]+),([0-9]+)"ve bunun yerine\1\2

1234,"123",1234
"234","123",1234
123,456,789

O zaman x <- read.csv(file="x.csv",header=FALSE)dosyayı okumak için kullanabilirsiniz .


22
Senaryo yazabileceğiniz her şeyi yapmalısınız. Bunu elle yapmak, çok fazla tekrarlanabilir olmamasının yanı sıra hata fırsatını da beraberinde getirir.
hadley
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.