1

我想在我的数据框(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
4

1 回答 1

3

我知道问题出在哪里——您需要“按原样”读取数据,方法是将参数添加as.is=TRUEread.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. 例如,dat直接在 R 中创建对象的正确方法是:

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

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

简而言之,永远记住as.is=TRUEand stringsAsFactors=FALSE,并学习如何使用该subset命令,你就不会出错!

希望这可以帮助 :)

于 2012-06-10T02:52:53.547 回答