Is there a way stop table from sorting in R

心已入冬 提交于 2021-02-08 05:30:44

问题


Problem setup: Creating a function to take multiple CSV files selected by ID column and combine into 1 csv, then create an output of number of observations by ID.

Expected:

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

I get:

> complete("specdata", 30:25)

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

Which is "wrong" because it has been sorted by id.

The CSV file I read from does have the data in descending order. My snippet:

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

And as near as I can tell, the third line is where sorting occurs. I broke out the expression and it happens in the table() call. I've not found any option or parameter I can pass to make something like sort=FALSE. You'd think...

Anyway. Any help appreciated!


回答1:


One way to get around this is...don't use table. Here's an example where I create three one-line data sets from your data. Then I read them in with a descending sequence, with read.table and it seems to be okay.

The real big thing here is that multiple data sets should be placed in a list upon being read into R. You'll get the exact order of data sets you want that way, among other benefits.

Once you've read them into R the way you want them, it's much easier to order them at the very end. Ordering of rows (for me) is usually the very last step.

> 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 three one-line files:

> 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)

Read them in using a 3:1 order:

> 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  

Then, if we change 3:1 to 1:3 the rows "comply" with our request

> 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

And just for 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



回答2:


So, the problem is in the output of table, which are sorted by default. For example:

> 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 

If you want to take the order of first appearance, you are going to get your hands a little bit dirty by recoding the table function:

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



回答3:


You may try something like this:

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



回答4:


In your case you are complaining about the actions of the table function with a single argument returning the items with the names in ascending order and you wnat them in descending order. You could have simply used the rev() function around the table call.

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

(I'm not sure what that last comma is doing in there.) The sort order in the original would not be expected to determine the order of a table operation. Generally R will return results with discrete labels sorted in alpha (ascending) order unless the levels of a factor item have been specified differently. That's one of those R-specific rules that may be difficult to intuit. The other R-specific rule that may be difficult to grasp (although not really a problem here) is that arguments are often expected to be in the form of R-lists.

It's probably wise to think about R-table objects at this point (and what happens with the as.data.frame call. table-objects are actually R-matrices, so the feature that you wanted to sort by was actually the rownames of that table object and are of class character:

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



回答5:


I just wanna share this homework I've done

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
}


来源:https://stackoverflow.com/questions/24842157/is-there-a-way-stop-table-from-sorting-in-r

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!