我有一个带有一些文件名和大小的数据框,我想将所有行的大小标准化为相同的单位(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")
我该怎么做?
谢谢
答案 0 :(得分:2)
有选项,但您需要将字符串切换为数字部分和标签部分。假设您仅有Mb
和Kb
(但可以扩展)的一个选项是使用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')]
如果您合并tidyr
和dplyr
,则可以在一个链中完成所有操作,如果您愿意:
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'的数字部分相乘删除sub
(sub("\\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