【问题标题】:Selecting rows with same result in different columns in R在R中的不同列中选择具有相同结果的行
【发布时间】:2012-06-08 17:28:23
【问题描述】:

我想在我的数据框(catch)中只选择“tspp.name”变量与“elasmo.name”变量相同的行。

例如,在这种情况下会选择第 #74807 行和 #74809 行,但不会选择第 #74823 行,因为 elasmo.name 是“skate”,而 tspp.name 是“Northern frog”。

我确信对此有一个简单的答案,但我还没有找到它。任何提示将不胜感激。

> catch[4:6,]
      gear tripID obsID sortie setID       date     time NAFO    lat   long      dur depth bodymesh
74807 GRL2 G00001     A      1    13 2000-01-04 13:40:00   2H 562550 594350 2.000000   377       80
74809 GRL2 G00001     A      1    14 2000-01-04 23:30:00   2H 562550 594350 2.166667   370       80
74823 GRL2 G00001     A      1    16 2000-01-05 07:45:00   2H 561450 593050 3.000000   408       80
      codendmesh mail.fil long.fil nbr.fil hook.shape hook.size hooks VTS tspp       tspp.name elasmo
74807         45       NA       NA      NA                   NA    NA 3.3 2211 Northern shrimp   2211
74809         45       NA       NA      NA                   NA    NA 3.2 2211 Northern shrimp   2211
74823         45       NA       NA      NA                   NA    NA 3.3 2211 Northern shrimp    211
          elasmo.name kept discard Tcatch     date.1 latitude longitude       EID
74807 Northern shrimp 2747      50   2797 2000-01-04 56.91667 -60.21667 G00001-13
74809 Northern shrimp 4919     100   5019 2000-01-04 56.91667 -60.21667 G00001-14
74823          Skates    0      50     50 2000-01-05 56.73333 -60.00000 G00001-16
                                 fgear
74807 Shrimp trawl (stern) with a grid
74809 Shrimp trawl (stern) with a grid
74823 Shrimp trawl (stern) with a grid

【问题讨论】:

  • catch[with(catch, tspp.name==elasmo.name),] 做你想做的事吗?
  • catch[which(catch$tspp.name == catch$elasmo.name),]
  • catch[catch$tspp.name == catch$elasmo.name,]
  • 布兰登和贾斯汀(第二个)答案之间的区别在于,如果 NA 值出现在 tspp.nameelasmo.name 中,它们是如何处理的。
  • subset(catch, tspp.name ==elasmo.name) 就像which 方法一样,只要测试的两个值中的任何一个都是 NA,NA 就会返回不匹配的行。

标签: r dataframe subset


【解决方案1】:

我知道问题出在哪里——您需要“按原样”读取数据,方法是将参数 as.is=TRUE 添加到 read.csv 命令(您可能用来加载所有内容)。如果没有这个,字符串会被存储为因子,并且上面建议的所有方法都将失败(正如您所发现的那样!)

正确读取数据后,您可以使用任一

catch[which(catch$tspp.name == catch$elasmo.name),]

subset(catch, tspp.name == elasmo.name)

要获得匹配的行 - 不要在第一个中省略 which,否则在与 NA 进行比较时代码将失败。

下面是一个 30 秒的示例,它使用了一个小型虚构数据集,明确说明了所有这些要点。

首先,在磁盘上创建一个如下所示的文本文件(我将其保存为“F:/test.dat”,但它可以保存在任何地方)...

col1~col2
a~b
a~a
b~b
c~NA
NA~d
NA~NA

让我们在不将因子转换为字符串的情况下加载它,只是为了看看上面提出的方法失败了:

> dat=read.csv("F:/test.dat",sep="~")  # don't forget to check the filename

> dat[which(dat$col1==dat$col2),]
Error in Ops.factor(dat$col1, dat$col2) : level sets of factors are different

> dat[dat$col1==dat$col2,]
Error in Ops.factor(dat$col1, dat$col2) : level sets of factors are different

> subset(dat,col1==col2)
Error in Ops.factor(col1, col2) : level sets of factors are different

这正是您遇到的问题。如果您输入dat$col1dat$col2,您将看到第一个具有因子水平a b c,而第二个具有因子水平a b d - 因此出现错误消息。

现在让我们做同样的事情,但这次“按原样”读取数据:

> dat=read.csv("F:/test.dat",sep="~",as.is=TRUE)  # note the as.is=TRUE

> dat[which(dat$col1==dat$col2),]
  col1 col2
2    a    a
3    b    b

> dat[dat$col1==dat$col2,]
     col1 col2
2       a    a
3       b    b
NA   <NA> <NA>
NA.1 <NA> <NA>
NA.2 <NA> <NA>

> subset(dat,col1==col2)
     col1 col2
2    a    a
3    b    b

如您所见,第一种方法(基于which)和第三种方法(基于subset)都给出了正确的答案,而第二种方法则因与NA的比较而感到困惑。我个人会提倡subset 方法,因为我认为它是最简洁的。

最后一点:还有其他方法可以让字符串作为数据框中的因素出现 - 为了避免所有这些令人头疼的问题,请始终记住在创建数据框时在末尾包含参数 stringsAsFactors = FALSE使用data.frame。例如,直接在 R 中创建对象 dat 的正确方法是:

dat=data.frame(col1=c("a","a","b","c",NA,NA), col2=c("b","a","b",NA,"d",NA),
                         stringsAsFactors=FALSE)

键入dat$col1dat$col2,您会看到它们已被正确解释。如果您再次尝试但省略stringsAsFactors 参数(或设置为 TRUE),您会看到那些该死的因素出现(就像从磁盘加载的狡猾的第一种方法一样)。

总之,永远记住as.is=TRUEstringsAsFactors=FALSE,并学习如何使用subset命令,你就不会出错!

希望这会有所帮助:)

【讨论】:

  • 很棒的答案@TimP 非常感谢您提供的所有详细信息。
猜你喜欢
  • 2017-12-31
  • 2020-12-20
  • 2017-02-14
  • 2015-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-08
  • 2012-05-25
相关资源
最近更新 更多