read.csv和fread为同一数据帧产生不同的结果

时间:2017-10-10 20:35:05

标签: r dataframe fread read.csv

data.table包中的

fread函数比read.cvs函数更快地读取大型csv文件。但是从“两个例程”的数据框输出可以看出“device _id”列的不同(参见最后3位数字)。为什么?这些函数中是否有参数可以正确读取它们?或者这是fread的正常行为? (它读取此数据文件的速度提高了10倍)。

# Read file
p<-fread("C:\\User\\Documents\\Data\\device.csv",sep=", integer64="character" )
> str(p)
         Classes ‘data.table’ and 'data.frame': 187245 obs. of  3 variables:
         $ device_id   : Factor w/ 186716 levels "-1000025442746372936",..: 89025 96789 140102 123523 45208 118633 32423 22215 54410 81947 ...
         $ phone_brand : Factor w/ 131 levels "E<U+4EBA>E<U+672C>""| __truncated__,"E<U+6D3E>""| __truncated__,..: 52 52 16 10 16 32 52 32 52 14 ...
         $ device_model: Factor w/ 1598 levels "1100","1105",..: 1517 750 561 1503 537 775 753 433 759 983 ...
         - attr(*, ".internal.selfref")=<externalptr>

> head(p)
                          device_id            brand                     device_model
            1: -8890648629457979026 <U+5C0F><U+7C73>                 <U+7EA2><U+7C73>
            2:  1277779817574759137 <U+5C0F><U+7C73>                             MI 2
            3:  5137427614288105724 <U+4E09><U+661F>                        Galaxy S4
            4:  3669464369358936369            SUGAR <U+65F6><U+5C1A><U+624B><U+673A>
            5: -5019277647504317457 <U+4E09><U+661F>                    Galaxy Note 2
            6:  3238009352149731868 <U+534E><U+4E3A>                             Mate

# Read file
p<-read.csv("C:\\Users\\Documents\\Data\\device.csv",sep=",")

# Convert device_id to character
> p$device_id<-as.character(p$device_id)

> str(p)
    'data.frame':   187245 obs. of  3 variables:
 $ device_id   : chr  "-8890648629457979392" "1277779817574759168" "5137427614288105472" "3669464369358936576" ...
 $ phone_brand : chr  "<U+5C0F><U+7C73>""| __truncated__ "<U+5C0F><U+7C73>""| __truncated__ "<U+4E09><U+661F>""| __truncated__ "SUGAR" ...
 $ device_model: chr  "<U+7EA2><U+7C73>""| __truncated__ "MI 2" "Galaxy S4" "<U+65F6><U+5C1A><U+624B><U+673A>""| __truncated__ ...

    > head(p)
                     device_id            brand                     device_model
        1 -8890648629457979392 <U+5C0F><U+7C73>                 <U+7EA2><U+7C73>
        2  1277779817574759168 <U+5C0F><U+7C73>                             MI 2
        3  5137427614288105472 <U+4E09><U+661F>                        Galaxy S4
        4  3669464369358936576            SUGAR <U+65F6><U+5C1A><U+624B><U+673A>
        5 -5019277647504317440 <U+4E09><U+661F>                    Galaxy Note 2
        6  3238009352149731840 <U+534E><U+4E3A>                             Mate

2 个答案:

答案 0 :(得分:1)

如果bit64库存在,fread将自动使用它来正确读取超过2 ^ 32 - 1的整数。

read.csv不这样做,所以它会溢出。

?fread的第一段提到了这一点:

  

read.table类似,但更快更方便。自动检测所有控件,例如sepcolClassesnrowsbit64::integer64类型也可以直接检测和读取,无需在转换前作为字符读取。

您正在使用integer64="character"选项,因此它们将被检测并作为字符读取。使用read.table时,不会检测到它们,也不会将其读作字符。如果希望read.csv的行为类似,则需要使用colClasses参数指定要在导入期间作为字符读取的列。当它被读入时,为时已晚。溢出已导致信息丢失,p$device_id<-as.character(p$device_id)无法“撤消”此问题。

  

这些功能中是否有参数可以正确读取?或者这是fread的正常行为?

是的,fread正在正确阅读,这是正常行为。 read.csv将需要更多的工作来正确读取内容 - 您需要使用colClassses参数将长整数读取为字符。它仍然会变慢。

答案 1 :(得分:1)

与teger一样优雅地讨论read.csv函数在读取64位数时有局限性。与fread类似,如果numerals参数定义为“no.loss”,read.cvs也可以。感谢所有这个问题的贡献者。

p<-read.csv("C:\\Users\\Documents\\Data\\device.csv",sep=",",encoding="UTF-8", numerals="no.loss" )

> head(p)
              device_id      phone_brand                     device_model
1: -8890648629457979026 <U+5C0F><U+7C73>                 <U+7EA2><U+7C73>
2:  1277779817574759137 <U+5C0F><U+7C73>                             MI 2
3:  5137427614288105724 <U+4E09><U+661F>                        Galaxy S4
4:  3669464369358936369            SUGAR <U+65F6><U+5C1A><U+624B><U+673A>
5: -5019277647504317457 <U+4E09><U+661F>                    Galaxy Note 2
6:  3238009352149731868 <U+534E><U+4E3A>                             Mate