【问题标题】:How do I subset/split this table bases on the values of one column in R?如何根据 R 中一列的值子集/拆分此表?
【发布时间】:2014-12-01 19:59:13
【问题描述】:

数据可以在这里找到:https://www.dropbox.com/s/l7pc11hhiwr8zzn/data.csv?dl=0,或者在图书馆 MASS 中作为nlschools

我想根据 nlschools$SES 的值拆分此表,将表划分为 nlschools$SES<=3030 < SES <= 40> 40 的表,并保留所有列。

我曾尝试使用像 0:30 这样的间隔使用 cut,但结果非常混乱,并且没有完整的列集。

我希望我想要达到的目标描述得足够清楚。

【问题讨论】:

  • @akrun 这是非常基本的,显然是错误的; 'sesLOW dropbox.com/s/v7n6c9sg9ca0iwi/akrun.csv?dl=0,其中每个索引现在只有 (-Inf, 30)、(30,40) 或 (40, Inf) 的值
  • 是的,我的意图是拆分整个数据集,保留所有列,并将其拆分为三个单独的数据集,例如使用sesLOW 将产生完整的表格,但仅限于具有 nlschools$SES

标签: r statistics


【解决方案1】:

试试这个:

indx <- with(nlschools,cut(SES, c(-Inf, 30, 40, Inf)))
lst <- split(nlschools, indx)
    
lapply(lst, head,2)
#$`(-Inf,30]`
#  lang   IQ class GS SES COMB
#1   46 15.0   180 29  23    0
#2   45 14.5   180 29  10    0

#$`(30,40]`
#  lang   IQ class GS SES COMB
#37   39 11.0  1082 25  33    1
#39   43 10.5  1280 31  33    1

#$`(40, Inf]`
#  lang IQ class GS SES COMB
#49   31  9  1280 31  50    1
#71   45 15  1880 28  50    0

如果您需要它作为单独的数据集:

list2env(setNames(lst, c("sesLOW", "sesMED", "sesHIGH")), envir=.GlobalEnv)
# <environment: R_GlobalEnv>


head(sesLOW,3)
#  lang   IQ class GS SES COMB.
#1   46 15.0   180 29  23    0
#2   45 14.5   180 29  10    0
#3   33  9.5   180 29  15    0

使用@Ujjwal 的帖子检查结果

identical(sesLOW, one)
#[1] TRUE

identical(sesMED, two)
#[1] TRUE

identical(sesHIGH, three)
#[1] TRUE

但是,在列表中进行所有分析/计算要比作为单独的数据集更容易。即使您可以使用lapplywrite.table/write.csv 等单独保存列表元素

更新

如果您想在list 中创建一个新列

names(lst) <- c("low","med", "high")#no need to rename the list elements though. You can directly use it as a vector in the `Map`
lst2 <- Map(function(x, y) {x[,"SEScat"] <- y;x }, lst, names(lst))
lapply(lst2, head,2)
#$low
#  lang   IQ class GS SES COMB SEScat
#1   46 15.0   180 29  23    0    low
#2   45 14.5   180 29  10    0    low

#$med
#  lang   IQ class GS SES COMB SEScat
#37   39 11.0  1082 25  33    1    med
#39   43 10.5  1280 31  33    1    med

#$high
#  lang IQ class GS SES COMB SEScat
#49   31  9  1280 31  50    1   high
#71   45 15  1880 28  50    0   high

【讨论】:

  • 谢谢。我可以理解在列表中进行分析更容易。例如,如果我希望创建一个额外的列,其中低、中、高遵循先前的阈值(nlschools$SEScat <- (pseudo: low if SES <=30, med if 30 < SES <=40, high if SES > 40) 之类的东西?
【解决方案2】:

试试:

one<-subset(nlschools, nlschools$SES <=30)
two<-subset(nlschools, nlschools$SES >30 &  nlschools$SES<=40)
three<-subset(nlschools, nlschools$SES >40)

【讨论】:

    【解决方案3】:

    回复您对@akrun 的评论,请尝试:

    > ddf$SEScat = with(ddf, ifelse(SES<=30,'low', ifelse(SES<=40, 'med', 'high')))
    > ll = split(ddf, ddf$SEScat)
    
    > head(ll[[1]])
          X lang   IQ class GS SES COMB SEScat
    49   49   31  9.0  1280 31  50    1   high
    71   71   45 15.0  1880 28  50    0   high
    82   82   47 12.0  1880 28  50    0   high
    85   85   33 13.0  1880 28  50    0   high
    90   90   31 10.5  1880 28  50    0   high
    145 145   50 13.5  2680 21  45    0   high
    > head(ll[[2]])
      X lang   IQ class GS SES COMB SEScat
    1 1   46 15.0   180 29  23    0    low
    2 2   45 14.5   180 29  10    0    low
    3 3   33  9.5   180 29  15    0    low
    4 4   46 11.0   180 29  23    0    low
    5 5   20  8.0   180 29  10    0    low
    6 6   30  9.5   180 29  10    0    low
    > head(ll[[3]])
        X lang   IQ class GS SES COMB SEScat
    37 37   39 11.0  1082 25  33    1    med
    39 39   43 10.5  1280 31  33    1    med
    40 40   25  8.5  1280 31  33    1    med
    42 42   41 11.0  1280 31  37    1    med
    45 45   21  9.5  1280 31  40    1    med
    52 52   29  8.5  1280 31  40    1    med
    

    【讨论】:

      猜你喜欢
      • 2023-04-06
      • 1970-01-01
      • 1970-01-01
      • 2021-09-11
      • 2015-05-13
      • 1970-01-01
      • 2021-08-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多