如何在R中的数据集中格式化数据?

时间:2016-04-05 03:00:09

标签: r dataframe

我有一个带有一些文件名和大小的数据框,我想将所有行的大小标准化为相同的单位(Mb):

这是我原来的数据:

  filename  size
1        A 100Kb
2        B 200Kb
3        C  30Kb
4        D   1Mb
5        E  10Mb

这就是我要找的(将大小标准化为Mb):

  filename  size (Mb)
1        A        0.1
2        B        0.2
3        C       0.03
4        D          1
5        E         10

这是我的原始数据框:

df=rbind(c("3/22/2016", "2:36:41 PM", "3.1Kb", "HiSeqControlSoftware.Options.cfg", "character(0)"),
c("3/22/2016", "2:36:41 PM", "32.7Kb", "Variability_HiSeq_E.bin", "character(0)"),
c("3/22/2016", "2:36:42 PM", "character(0)", "Variability_HiSeq_E.bin", "74"),
c("3/22/2016", "2:36:42 PM", "character(0)", "HiSeqControlSoftware.Options.cfg", "76"),
c("3/22/2016", "2:36:42 PM", "20Kb", "HK7N2CCXX.xml", "character(0)"),
c("3/22/2016", "2:36:42 PM", "character(0)", "HK7N2CCXX.xml", "26"),
c("3/22/2016", "2:36:42 PM", "9.4Kb", "runParameters.xml", "character(0)"))
df = as.data.frame(df)
colnames(df) = c("date","timestamp","filesize","filename","time")

我该怎么做?

谢谢

2 个答案:

答案 0 :(得分:2)

有选项,但您需要将字符串切换为数字部分和标签部分。假设您MbKb(但可以扩展)的一个选项是使用substr

df$size <- as.character(df$size)

df$size <- ifelse(substr(df$size, nchar(df$size)-1, nchar(df$size)) == 'Mb',
                  as.numeric(substr(df$size, 1, nchar(df$size)-2)),
                  as.numeric(substr(df$size, 1, nchar(df$size)-2))/1000)

names(df)[2] <- 'size_Mb'
df
#   filename size_Mb
# 1        A    0.10
# 2        B    0.20
# 3        C    0.03
# 4        D    1.00
# 5        E   10.00

tidyr::separate也可以通过将substr分成两列来替换所有size,从而简化了代码:

library(tidyr)
df <- separate(df, size, c('size', 'label'), sep = -3, convert = TRUE)
df$size_Mb <- ifelse(df$label == 'Mb', df$size, df$size/1000)
df <- df[,c('filename', 'size_Mb')]

如果您合并tidyrdplyr,则可以在一个链中完成所有操作,如果您愿意:

library(tidyr)
library(dplyr)
df %>% separate(size, c('size', 'label'), sep = -3, convert = TRUE) %>% 
    mutate(size = ifelse(label == 'Mb', size, size/1000)) %>% 
    select(-label)

如果您愿意,可以使用正则表达式与

分开
df$label <- sub('\\d+(\\w+)', '\\1', df$size)
df$size <- as.numeric(sub('(\\d+)\\w+', '\\1', df$size))

答案 1 :(得分:1)

我们可以使用gsubfn将{size}中的非数字子字符串替换为''/1e3,然后使用eval(parse获取预期的输出。

library(gsubfn)
unname(sapply(gsubfn('[A-Za-z]+', list(Mb='', Kb = '/1e3'), 
    as.character(df$size)), function(x) eval(parse(text=x))))
#[1]  0.10  0.20  0.03  1.00 10.00

或者使用sub中的base R替换'size'中的数字子字符串,将其与键/值向量(setNames(c(1/1e3, 1), c("Kb", "Mb")))匹配,并与'size'的数字部分相乘删除subsub("\\D+", "", df$size))的非数字字符。

df$size_Mb <- (setNames(c(1/1e3, 1), c("Kb", "Mb")) [sub("\\d+", "", 
   df$size)]) * as.numeric(sub("\\D+", "", df$size))
df$size_Mb
#[1]  0.10  0.20  0.03  1.00 10.00

<强>更新

对于新数据集

 v1 <- setNames(c(1/1e3, 1), c("Kb", "Mb"))
 v1[sub("[^[:alpha:]]+", "", df$filesize)]*
       as.numeric(sub("[[:alpha:]]+", "", df$filesize))
 #    Kb     Kb   <NA>   <NA>     Kb   <NA>     Kb 
 #0.0031 0.0327     NA     NA 0.0200     NA 0.0094