【问题标题】:R: Create a new column with multiple categories(levels) based on the critera of two other columnsR:根据其他两列的标准创建具有多个类别(级别)的新列
【发布时间】:2013-10-16 14:31:44
【问题描述】:

我的数据如下所示

> head(CPUE)
    Lon.rect Lat.rect         q1          q4
    1     13.5    54.25  0.1930234  1.76096260
    2     13.5    54.75 11.6866331 19.06265440
    3     13.5    55.25 24.2532215 33.64530930
    4     13.5    55.75  0.2113688  0.05731537
    5     14.5    54.25  2.5600818  8.72482876
    6     14.5    54.75 85.8657297 34.08524869

现在,我想做的是创建一个新列,其中包含多个类别(级别),基于子集“Lon.rect”和“Lat.rect”的数据组合。我想根据每列中的数据为类别命名不同的名称。例如对于 Lon.rect = 13.5, Lat.rect = 54.25,新列中的类别名称将为“1A”,而在第二行中,类别名称为“1B”,因为 Lat.rect 包含不同的数据。第 5 行将是“2A”,依此类推。

"Lon.rect" & "Lat.rect" 包含坐标(如果这对任何人都重要的话)并且还有更多的组合。从 Lot 13.5 到 22.5 和 Lat 54.25 到 58.75。

我通过以下方式创建了一个名为“subdiv”的新列:

CPUE["subdiv"] <- NA

整个数据集现在看起来:

   > head(CPUE)
      Lon.rect Lat.rect         q1          q4 subdiv
    1     13.5    54.25  0.1930234  1.76096260     NA
    2     13.5    54.75 11.6866331 19.06265440     NA
    3     13.5    55.25 24.2532215 33.64530930     NA
    4     13.5    55.75  0.2113688  0.05731537     NA
    5     14.5    54.25  2.5600818  8.72482876     NA
    6     14.5    54.75 85.8657297 34.08524869     NA

我知道我可以像下面这样输入所有内容,但这需要很长时间,因为它需要大量数据。

CPUE$subdiv[CPUE$Lon.rect>=13 & CPUE$Lon.rect<=14 & CPUE$Lat.rect>=54.0 & CPUE$Lat.rect<=54.5] <- "1A"
CPUE$subdiv[CPUE$Lon.rect>=13 & CPUE$Lon.rect<=14 & CPUE$Lat.rect>=54.5 & CPUE$Lat.rect<=55.0] <- "1B"
CPUE$subdiv[CPUE$Lon.rect>=13 & CPUE$Lon.rect<=14 & CPUE$Lat.rect>=55.0 & CPUE$Lat.rect<=55.5] <- "1C"

我希望我的描述很清楚,否则不要犹豫与我联系! 如果有人对任何步骤有好的解决方案,请回信! 谢谢! /菲利普

编辑:

关于我的问题的更多信息

上面列的名称; “1A”、“1B”和“2A”只是说明我希望源列之间的关系如何的示例,我真的想给它们命名其他东西,但是如果有人感兴趣,我在下面得到了一些很好的帮助这个。

就我而言,我想在从 37 开始的整数之后命名 Lat.rect 列。Lon.rect 会有点棘手。该名称由一个字母和一个数字组成,从 G3 开始(在本例中)。每个字母的最大数字是 9,然后下一个字母从 0 开始,所以 G9 之后的下一个名称是 H0。

如果有帮助,我不需要脚本来为整个字母表进行这种组合。最小可能的组合(我所有的数据集,目前不需要)是 F9,最大是 H9。

我还希望首先使用 lat 名称,然后使用 lon 名称。如果首先交换 data.frame 中列的位置然后创建名称会更容易,那就没问题了。

第一行的最终组合是“37G3”,然后是第二行“38G3”。第 5 行将是“37G4”。

如果有人能帮助我完成第二部分,我将不胜感激!

【问题讨论】:

  • 您可以使用pastefactor,而不是命名新列。 with(CPUE, factor(paste(Lon.rect, Lat.rect)))。如果您尝试首先“分桶”您的数字坐标,请使用cut
  • 嗨,问题是我不想将新列中的类别命名为与源列相同。我想给他们一个不同的名字,但仍然基于源的级别。不过谢谢!这在其他情况下可能会有所帮助。我没有真正得到cut 功能,抱歉。我是新手。我刚收到回复“'x' 必须是数字”。

标签: r calculated-columns


【解决方案1】:

使用interaction 是在您的列中从unique 组合factors 获取levels 的一种方法。但是我在前两列使用match,在unique 元素的table 中查找每个元素的位置。然后我可以将paste 这些值放在一起并使用as.factor 强制转换为factor 变量。我发现它使关卡的重命名对我来说更直观,而且它也不依赖于 data.frame 被排序...

a <- match( df[,1] , unique( df[,1] ) )
b <- letters[ match( df[,2] ,  unique( df[,2] ) ) ]

df$new <- as.factor( paste0( a , b ) )
#  Lon.rect Lat.rect         q1          q4 new
#1     13.5    54.25  0.1930234  1.76096260  1a
#2     13.5    54.75 11.6866331 19.06265440  1b
#3     13.5    55.25 24.2532215 33.64530930  1c
#4     13.5    55.75  0.2113688  0.05731537  1d
#5     14.5    54.25  2.5600818  8.72482876  2a
#6     14.5    54.75 85.8657297 34.08524869  2b

【讨论】:

  • 我会使用 expand.grid 并合并,但这更简单
  • @statquant 似乎更容易获得所需的标签。干杯。
  • 感谢您的快速回答,可惜我已经离开了。它可以按照我在问题中提出的要求进行。现在问题是“1A”只是一个名字的例子,所以纯数字和字母在我的情况下不起作用。但也许是一种组合,如果有可能告诉 R 从哪个数字/字母开始。我想在从 37 开始的整数之后命名 lon 列。lat 会有点棘手。该名称由一个字母和一个数字组成,从 G3 开始(在本例中)。每个字母的最大数字是 9,然后下一个字母从 0 开始,所以在 G9 之后,它将是 H0。谢谢
  • 显然我的声望太低了,不能给你提个醒,对不起。
【解决方案2】:

更一般地,如果您的数据不是这样排序的(按lon,然后按lat),并且您希望subdiv 包含lotlan 的所有levels,您可以:

    CPUE <- data.frame(lon = as.vector(replicate(4, sample(13.5:22.5, 10, T))),
                       lat = as.vector(replicate(4, sample(seq(54, 56.25, 0.25), 10, T))))

    num <- findInterval(CPUE$lon, sort(unique(CPUE$lon)))
    lett <- findInterval(CPUE$lat, sort(unique(CPUE$lat)))

    CPUE$subdiv <- paste(num, LETTERS[lett], sep = "")

    CPUE
        lon   lat subdiv
    1  13.5 54.50     1C #this is the first possible "lon" and the third possible "lat"
    2  15.5 54.50     3C
    3  20.5 55.25     8F #this is the eigth possible "lon" and the sixth possible "lat"
    4  19.5 54.00     7A
    5  16.5 55.75     4H

注意:如果 (1) 您不想包含“lon”和“lat”的所有可能级别,并且 (2) 您的数据未排序,则此方法将不起作用已发布。

编辑

可能是这样的?:

    CPUE <- data.frame(lon = sort(rep(13.5:22.5, 13)),
                       lat = rep(seq(54.25, 60.25, 0.5), 10))

    lat_names <- findInterval(CPUE$lat, sort(unique(CPUE$lat))) + 36

    lon_names <- as.vector(sapply(LETTERS, paste, 0:9, sep = ""))
    lon_names <- lon_names[match("G3", lon_names):length(lon_names)]
    lon_names <- lon_names[findInterval(CPUE$lon, sort(unique(CPUE$lon)))]

    CPUE$subdiv <- paste(lat_names, lon_names, sep = "")

    > CPUE
         lon   lat subdiv
    1   13.5 54.25   37G3
    2   13.5 54.75   38G3
    3   13.5 55.25   39G3
    4   13.5 55.75   40G3
    5   13.5 56.25   41G3
    6   13.5 56.75   42G3
    7   13.5 57.25   43G3
    8   13.5 57.75   44G3
    9   13.5 58.25   45G3
    10  13.5 58.75   46G3
    11  13.5 59.25   47G3
    12  13.5 59.75   48G3
    13  13.5 60.25   49G3
    14  14.5 54.25   37G4
    15  14.5 54.75   38G4
    16  14.5 55.25   39G4
    17  14.5 55.75   40G4
    18  14.5 56.25   41G4
    19  14.5 56.75   42G4
    20  14.5 57.25   43G4
    ....

【讨论】:

  • 谢谢! Alt1 似乎改变了我的 lon&lat 的值,不知道为什么。 Alt 2 在我的情况下会更相关。然而,经度真的从 13.5 到 22.5,纬度从 54.25 到 60.25。我试图将其更改为 lon = sort(rep(13.5:22.5, 10)), lat = rep(seq(54.25, 60.25, 0.5), 13)) 似乎不起作用。得到回复arguments imply differing number of rows: 100, 130。现在问题是“1A”只是一个名字的例子,所以纯数字和字母在我的情况下不起作用。但也许是一种组合,如果可以告诉 R 从哪个数字/字母开始......
  • 我想以从 37 开始的整数命名 lon 列。lat 会有点棘手。该名称由一个字母和一个数字组成,从 G3 开始(在本例中)。每个字母的最大数字是 9,然后下一个字母从 0 开始,所以在 G9 之后,它将是 H0。你现在会怎么做?感谢所有的帮助。对不起,我不能给你的答案,我的代表太低了。 :/ 感谢所有的帮助!
  • @balconydorr:我更新了我的答案。我假设您的数据像您发布的样本一样一直向下排序(即假设 CPUE 是您的实际数据)。看看它是否适合你。
  • 是的,成功了!非常感谢!但是,我想将我的 q1 和 q4 列保留在新的 df 中。现在我只需要排除一些坐标,但我想我可以通过在某处输入 !number 以及一些其他代码来做到这一点。
  • 排除不存在的行非常容易。我使用了合并功能并通过公共行定义了它。 (虽然它创建了新列,我刚刚删除了)再次感谢。 newCPUE2&lt;- merge(CPUE,newCPUE,by.x=c('Lon.rect','Lat.rect'), by.y=c('Lon.rect','Lat.rect'))
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-07-05
  • 2021-02-09
  • 2021-12-24
  • 2018-09-14
  • 2021-08-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多