因此,我将多个文本文件中包含的值分箱到设定范围时遇到了一些问题。我已经在网上查看了各种软件包,并且遇到了可以bin值的sm,你也可以指定bin范围: -
xb <- binning(x, breaks=seq(-4,4,by=0.5))
但实施此问题时我遇到了一些问题。我不能指定上限,因为我不知道上限是什么(文件有从仪器获得的数千个值),我有25个文件,每个文件包含数千个值,我需要在同时(我需要随后取所有这些分箱值的中位数),我只是在阅读文本文件时遇到麻烦。我表演: -
read.table("foobar.txt", sep=",")
只读取一个文本文件,因为所有值都由','分隔,但它似乎无法处理。此外,我希望能够以给定的0.0005范围对值进行分级(例如,值在200.0000 - 200.0005之间分箱,200.0005 - 200.0010等等)
我正在使用的文本文件是.txt,其值由逗号分隔,包含数千个值。我的想法是,我将值分组到一个范围内的组中,然后取这些代表该特定bin的值的中值。例如,如果我有值1,1,2,3,3,4,5,5,6,7,7,9,10并且我将bin的范围设置为2,那么第一个bin将包含1,1,2,第二个3,3,4,第三个5,5,6等,所有这些值的中位数用于表示仓,第一个仓的中值为1,第二个,第三个,第三个(我知道在这个例子中,取中值可能看起来毫无意义,但我得到的数据是有道理的)
有没有办法在多个文本文件中读取值并按照我描述的方式同时处理它们?是否有这样的包装,我可以看一下这本手册?任何建议或提示将不胜感激!
答案 0 :(得分:3)
有几种方法可以做到,我将提供一种使用基本功能的方法。 (另一种方法是使用dplyr
,也非常适合这种情况。但是,基本示例应该足够简单。)
(这只是因为我们没有您的任何数据。)
n <- 10
for (ii in 1:3) {
dat <- runif(n)
writeLines(paste(dat, collapse = ','),
con = sprintf('user2062207-file%s.txt', ii))
}
readLines('user2062207-file1.txt')
## [1] "0.929472318384796,0.921938128070906,0.707776406314224,0.236701443558559,0.271322417538613,0.388766387710348,0.422867075540125,0.324589917669073,0.92406965768896,0.171326051233336"
这是你开始的地方,假设你有一个简单的模式来查找文件。
fnames <- list.files(pattern = 'user2062207-file.*.txt')
allData <- unlist(sapply(fnames, read.table, sep = ','))
allRange <- range(allData)
df <- data.frame(x = allData)
head(df)
## x
## 1 0.9294723
## 2 0.9219381
## 3 0.7077764
## 4 0.2367014
## 5 0.2713224
## 6 0.3887664
dim(df)
## [1] 30 1
下面的{floor,ceiling} +/- binSize
是因为垃圾箱只包含范围的一侧(默认值:右侧),因此最小值不会被分箱。它还确保箱子在圆形边界上。
binSize <- 0.05
allBins <- seq(floor(allRange[1] / binSize) * binSize,
ceiling(allRange[2] / binSize) * binSize,
by = binSize)
## bin the data
df$bin <- cut(df$x, breaks = allBins)
head(df)
## x bin
## 1 0.9294723 (0.9,0.95]
## 2 0.9219381 (0.9,0.95]
## 3 0.7077764 (0.7,0.75]
## 4 0.2367014 (0.2,0.25]
## 5 0.2713224 (0.25,0.3]
## 6 0.3887664 (0.35,0.4]
sapply(levels(df$bin), function(lvl) median(df$x[df$bin == lvl], na.rm = TRUE))
## (0,0.05] (0.05,0.1] (0.1,0.15] (0.15,0.2] (0.2,0.25] (0.25,0.3] (0.3,0.35]
## 0.03802277 NA 0.11528715 0.18195392 0.22918094 0.27132242 0.33626971
## (0.35,0.4] (0.4,0.45] (0.45,0.5] (0.5,0.55] (0.55,0.6] (0.6,0.65] (0.65,0.7]
## 0.38009637 0.42184059 NA 0.53826028 0.57820253 0.64165116 0.67825992
## (0.7,0.75] (0.75,0.8] (0.8,0.85] (0.85,0.9] (0.9,0.95] (0.95,1]
## 0.74243926 NA 0.80759621 0.88974267 0.92406966 0.95691077
这是一个许多其他选择可能有利的领域。例如,基函数by
可以工作,尽管处理它的数据结构并不总是直观的,即使函数调用本身很容易阅读:
head(by(df$x, df$bin, median, na.rm = TRUE))
## df$bin
## (0,0.05] (0.05,0.1] (0.1,0.15] (0.15,0.2] (0.2,0.25] (0.25,0.3]
## 0.03802277 NA 0.11528715 0.18195392 0.22918094 0.27132242
您也可以轻松使用dplyr
。此示例以原始allData
和allBins
:
library(dplyr)
data.frame(x = allData) %>%
mutate(bin = cut(x, breaks = allBins)) %>%
group_by(bin) %>%
summarise(median(x))
## Source: local data frame [17 x 2]
## bin median(x)
## 1 (0,0.05] 0.03802277
## 2 (0.1,0.15] 0.11528715
## 3 (0.15,0.2] 0.18195392
## 4 (0.2,0.25] 0.22918094
## 5 (0.25,0.3] 0.27132242
#### ..snip..
第一个示例保留空箱,而其他方法不知道空箱。使用by
和dplyr
可能还有其他方法可以包含这些空箱,但这似乎就足够了。
经过一段时间的聊天,确定数据范围太宽,bin宽度为0.0005。设计了一个更好的解决方案。 (没有提供的样本数据,抱歉,不是我的...)我将使用随机数据来模仿这个过程:
set.seed(42)
x <- 5e7 * runif(5e5)
library(dplyr)
binSize <- 0.0005
df <- data.frame(dat = sort(x))
df$bin <- floor(df$dat / binSize) * binSize
head(df)
## dat bin
## 1 410.9577 410.9575
## 2 456.6275 456.6270
## 3 552.3674 552.3670
## 4 875.4898 875.4895
## 5 1018.6806 1018.6805
## 6 1102.2436 1102.2435
system.time(results <- df %>% group_by(bin) %>% summarize(med = median(dat)))
## user system elapsed
## 12.08 0.00 12.11
head(results)
## Source: local data frame [6 x 2]
## bin med
## 1 410.9575 410.9577
## 2 456.6270 456.6275
## 3 552.3670 552.3674
## 4 875.4895 875.4898
## 5 1018.6805 1018.6806
## 6 1102.2435 1102.2436