在R中的不同列中选择具有相同结果的行

时间:2012-06-08 17:28:24

标签: r dataframe subset

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

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

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

> 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

1 个答案:

答案 0 :(得分:3)

我知道问题是什么 - 您需要通过将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命令,这样你就不会出错!

希望这会有所帮助:)