【问题标题】:Is there a way stop table from sorting in R有没有办法阻止表格在 R 中排序
【发布时间】:2014-09-10 14:30:09
【问题描述】:

问题设置:创建一个函数以获取由 ID 列选择的多个 CSV 文件并组合成 1 个 csv,然后按 ID 创建一个观察数的输出。

预期

complete("specdata", 30:25) ##notice descending order of IDs requested

##   id nobs
## 1 30  932
## 2 29  711
## 3 28  475
## 4 27  338
## 5 26  586
## 6 25  463

我明白了:

> complete("specdata", 30:25)

  id nobs
1 25  463
2 26  586
3 27  338
4 28  475
5 29  711
6 30  932

这是“错误的”,因为它是按 id 排序的。

我从中读取的 CSV 文件确实具有降序排列的数据。我的sn-p:

dfTable<-read.csv("~/progAssign1/specdata/tmpdata.csv")
ccTab<-complete.cases(dfTable)
xTab3<-as.data.frame(table(dfTable$ID[ccTab]),)
colnames(xTab3)<-c("id","nobs")

据我所知,第三行是排序发生的地方。我打破了表达式,它发生在 table() 调用中。我没有找到任何可以传递的选项或参数来制作类似 sort=FALSE 的东西。你会想……

无论如何。任何帮助表示赞赏!

【问题讨论】:

  • 我只想重新排序来自table 的输出,请参阅order。如果你想了解 R-way-of-doing-things 我会看看 dplyr 包和任何其他 Hadley Wickham 包。
  • 回答你的问题:table 中没有隐藏开关(它依赖于 tabulate,它本身依赖于 C 函数)=> 所以你必须自己重新排序。
  • @PaulHiemstra 我会认为 dplyr 是一个很好的方式来看待做事的“R-way”。使用中缀运算符并从左到右传递结果并不是 R 编程的典型做法。我同意,一旦你学会了“功能性地”思考(通过在函数中包含参数),dplyr 非常光滑并且是对 R 世界的真正礼物,但在我看来,它是 R 来自有点非典型(但公认优雅) 观点。
  • 我不理解您反复抱怨希望制表操作的输入顺序会受到输入顺序的影响。无论那是什么,这似乎都不是“现代”计算机语言的标志。 R 不是 SAS,也不是 C,也不是 C++。它是一个统计工作台。进步的唯一方法是关注底层结构,学会使用listtapplyave、“[”、“[[”、ordermatchmerge。然后您可以决定是否要使用 data.table 或 dplyr 或 reshape2,因为每个本质上都是基本 R 的一个分支。
  • @BondedDust:我没有抱怨。我在观察。

标签: r sorting csv


【解决方案1】:

所以,问题出在table 的输出中,它们是默认排序的。例如:

> r = sample(5,15,replace = T)
> r
 [1] 1 4 1 1 3 5 3 2 1 4 2 4 2 4 4
> table(r)
r
1 2 3 4 5 
4 3 2 5 1 

如果你想按第一次出现的顺序,你会通过重新编码table函数来弄脏你的手:

unique_r = unique(r)
table_r = rbind(label=unique_r, count=sapply(unique_r,function(x)sum(r==x)))
table_r
      [,1] [,2] [,3] [,4] [,5]
label    1    4    3    5    2
count    4    5    2    1    3

【讨论】:

  • 是的......所以我对在一行代码中做事并且有时不得不编写更多代码的评论。我对 R 的抱怨是“默认情况下”——如果它是默认值,我可以覆盖它,我会更高兴:)。但感谢您的信息和回复!我已经投票了,但我在 atm 的声誉很差......
  • 我认为“问题”在于factortable 调用:table(factor(r, levels = c(1, 4, 3, 5, 2)))
【解决方案2】:

解决此问题的一种方法是...不要使用table。这是一个示例,我从您的数据中创建了三个单行数据集。然后我按降序读取它们,read.table 似乎没问题。

真正重要的是,多个数据集在读入 R 时应放在一个列表中。您将获得所需的数据集的确切顺序,以及其他好处。

一旦您按照您想要的方式将它们读入 R 中,在最后订购它们就容易多了。行排序(对我而言)通常是最后一步。

> dat <- read.table(h=T, text = "id nobs
  1 25  463
  2 26  586
  3 27  338
  4 28  475
  5 29  711
  6 30  932")

写三个单行文件:

> write.table(dat[3,], "dat3.csv", row.names = FALSE)
> write.table(dat[2,], "dat2.csv", row.names = FALSE)
> write.table(dat[1,], "dat1.csv", row.names = FALSE)

使用3:1 命令阅读它们:

> do.call(rbind, lapply(3:1, function(x){ 
       read.table(paste0("dat", x, ".csv"), header = TRUE) 
  }))
#   id nobs
# 1 27  338
# 2 26  586
# 3 25  463  

然后,如果我们将 3:1 更改为 1:3 行“符合”我们的要求

> do.call(rbind, lapply(1:3, function(x){
      read.table(paste0("dat", x, ".csv"), header = TRUE)
  }))
#   id nobs
# 1 25  463
# 2 26  586
# 3 27  338

只为fun

> fun <- function(z){
      do.call(rbind, lapply(z, function(x){ 
          read.table(paste0("dat", x, ".csv"), header = TRUE) }))
  }
> fun(c(2, 3, 1))
#   id nobs
# 1 26  586
# 2 27  338
# 3 25  463

【讨论】:

  • 我从 rbind 和其他东西开始。问题是我在上课的第 2 周,但这些都没有涵盖:太令人沮丧了!我试图远离更深层次的东西,但我想我会在没有完全理解的情况下“借用”它,只是因为它明天到期。然后我会为此编写一个函数,因为它对我来说更有意义。谢谢!
【解决方案3】:

你可以试试这样的:

t1 <- c(5,3,1,3,5,5,5)
as.data.frame(table(t1)) ##result in ascending order
 # t1 Freq
#1  1    1
#2  3    2
#3  5    4

 t1 <- factor(t1)
 as.data.frame(table(reorder(t1, rep(-1, length(t1)),sum)))
# Var1 Freq
#1    5    4
#2    3    2
#3    1    1

【讨论】:

  • 好东西要知道,但在这种情况下,我必须检测到请求是按降序排列的,然后编写一个“if”来使用它或放弃它,因为请求是按升序...
【解决方案4】:

在您的情况下,您抱怨 table 函数的操作,其中一个参数返回名称按升序排列的项目,而您按降序排列它们。您可以简单地在 table 调用周围使用 rev() 函数。

xTab3<-as.data.frame( rev( table( dfTable$ID[ccTab] ) ),)

(我不确定最后一个逗号在那里做了什么。)原始的排序顺序不会决定表操作的顺序。通常,R 将返回具有按 alpha(升序)顺序排序的离散标签的结果,除非已以不同方式指定因子项目的级别。这是可能难以直觉的那些特定于 R 的规则之一。另一个可能难以掌握的特定于 R 的规则(尽管在这里不是真正的问题)是参数通常被期望采用 R 列表的形式。

此时考虑 R 表对象可能是明智的(以及 as.data.frame 调用会发生什么。table 对象实际上是 R 矩阵,因此您想要排序的特征实际上是该表对象的行名和类字符:

r = sample(5,15,replace = T)
table(r)
#r
#2 3 4 5 
#5 3 2 5 
rownames(table(r))
#[1] "2" "3" "4" "5"

str(as.data.frame(table(r)))
#-------
'data.frame':   4 obs. of  2 variables:
 $ r   : Factor w/ 4 levels "2","3","4","5": 1 2 3 4
 $ Freq: int  5 3 2 5

【讨论】:

  • 我认为逗号是上一次尝试遗留下来的... R 似乎让简单的事情变得更困难,而以使困难的事情变得更简单为代价。不过,我很感谢您的回复。
  • 而且 rev() 很高兴知道,但是,在这种情况下,我需要再次编写流控制代码,以确定是否需要反转表格。
【解决方案5】:

我只想分享我做的这个作业

complete <- function(directory, id=1:332){
    setwd("E:/Coursera")
    files <- dir(directory, full.names = TRUE)
    data <- lapply(files, read.csv)
    specdata <- do.call(rbind, data)

    cleandata <- specdata[!is.na(specdata$sulfate) & !is.na(specdata$nitrate),]
    targetdata <- data.frame(Date=numeric(0), sulfate=numeric(0), nitrate=numeric(0), ID=numeric(0))
    result<-data.frame(id=numeric(0), nobs=numeric(0))

    for(i in id){
        targetdata <- cleandata[cleandata$ID == i, ]
        result <- rbind(result, data.frame(table(targetdata$ID)))
    }

    names(result) <- c("id","nobs")
    result
}

【讨论】:

    【解决方案6】:

    一种尚未有人提出的简单解决方案是将table()unique() 函数结合使用。 unique() 函数执行您正在查看的行为(按出现顺序列出唯一 ID)。 在你的情况下,它会是这样的:

    dfTable<-read.csv("~/progAssign1/specdata/tmpdata.csv")
    ccTab<-complete.cases(dfTable)
    x<-dfTable$ID[ccTab] #unique IDs
    xTab3<-as.data.frame(table(x)[unique(x)],) #here you sort the "table()" result in order of appearance
    colnames(xTab3)<-c("id","nobs")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-05
      • 1970-01-01
      • 2019-10-20
      • 1970-01-01
      • 1970-01-01
      • 2020-05-04
      • 1970-01-01
      相关资源
      最近更新 更多