【问题标题】:Searching Two Columns in a Data Frame in R在 R 中搜索数据框中的两列
【发布时间】:2017-07-04 04:29:09
【问题描述】:

我有一个关于在 R 中搜索值的问题,它实际上与昨天发布的一个问题有点相似(在这里给出:Searching a vector/data table backwards in R)除了我认为我的问题有点复杂(而且与我想做的相反),而且由于我对 R 很陌生,所以我不太确定如何解决这个问题。

我有一个类似于下面给出的数据框,我希望找到我当前的索引值,其中Times 列与我当前时间不同,Midquote 列没有@ 987654324@值。

Index               Times    |    Midquote
                -----------------------------
   1            10:30:45.58  |    5.319
   2            10:30:45.93  |    5.323
   3            10:30:45.104 |    5.325
   4            10:30:45.127 |    5.322
   5            10:30:45.188 |    5.325
   6            10:30:45.188 |    NA
   7            10:30:45.212 |    NA
   8            10:30:45.231 |    5.321
   9            10:30:45.231 |    5.321

如果我们从数据框的底部开始并将其作为“当前”时间,则发现它位于索引 9 处,其 Times 值为 10:30:45.231Midquote 值为5.321,那么如果我想找到时间与我当前时间不同的第一个索引,我们看到这是索引7,它的时间为10:30:45.212(因为索引8具有相同的时间) .但我们还看到,在索引 7 处,Midquote 的值是 NA,所以我现在必须再次检查数据框。索引 6 再次具有不同的时间(即 10:30:45.188 )但它在 Midquote 列中也有一个 NA 值,所以再次向上移动到索引 5 我们看到 Times 列有不同的时间我当前的时间(即再次10:30:45.188)并且Midquotes 的值是5.325

因此,由于索引 5 处的时间是 10:30:45.188(这与我当前的时间不同,即 10:30:45.231)并且由于索引 5 处的 Midquote 值不是 NA,我希望获得输出“5”,因为它是同时满足这两个条件的索引值。

我的问题是,有没有一种好的方法可以做到这一点?如果这是一个简单的问题,我很抱歉,我对 R 很陌生,而且我对使用数据框了解不多......

编辑:如果可能的话,我也希望最好不要在数据框中添加另一列(如我上面提到的链接的顶部答案中给出的那样)

【问题讨论】:

  • 你能显示预期的输出吗?
  • 对不起,你是什么意思?如果这是您要问的,我希望能够从数据框中获取索引 5,因为 Time 与我当前的时间不同(因为我从数据框的最底部开始)和 @ 987654345@不是NA
  • 显示您希望数据的外观,即您的问题的“答案”对于您的示例数据是什么样的。如果您显示数据中所有相关行的答案(不仅仅是索引 9),这会有所帮助,因为这可以使确切的规则更加清晰。
  • 很抱歉,我现在将编辑我的主题

标签: r search dataframe data.table


【解决方案1】:

处理日期很困难,尤其是小数秒。 如果您可以将时间转换为双打,那么使用起来会更容易。 假设你的“时代”是为了你可以使用这个

library(magrittr)
which(df$Times < df[9,1] & !is.na(df$Midquote)) %>% max()

which 给出了一个“索引”向量,其中“时间”小于 9 中的值,并且“中间引用”不是 NA。 %&gt;% 将向量发送到max(),它给出了最高值。这很不优雅,但可以完成工作。

【讨论】:

    【解决方案2】:

    如果我理解正确,请检查这是否是您期望的输出。

    ind<-function(t,df){
        ind<-t
        while(t>1){
           t=t-1
            if((df$Times[t]!=df$Times[ind]) && (!is.na(df$Midquote[t]))){
                return(t)
            }
        }
    }
    sapply((nrow(data):1),FUN = ind,data)
    
    #[[1]]
    #[1] 5
    
    #[[2]]
    #[1] 5
    
    #[[3]]
    #[1] 5
    
    #[[4]]
    #[1] 4
    
    #[[5]]
    #[1] 4
    
    #[[6]]
    #[1] 3
    
    #[[7]]
    #[1] 2
    
    #[[8]]
    #[1] 1
    
    #[[9]]
    #NULL
    

    输出系列对应于从最后一行开始的 data.frame 的关联索引。

    解释:ind 取行号的值作为当前行,而t 取值从ind-1 到1。df 取整个data.frame 作为输入然后while循环用于检查df$Times[t]df$Midquote[t]的时间和中间引用值是否满足要求的条件。如果是,则返回索引,否则循环继续,直到到达第一行。

    不对特定的当前行使用sapply

     ind(9,df)
     [1] 5
    

    【讨论】:

    • 谢谢,这似乎是我正在寻找的东西 :) 你能解释一下 sapply 函数需要什么吗?我尝试用函数输入它,但它不能正常工作,我不太熟悉它的作用
    • sapply 通常用于在不使用 for 循环的情况下循环遍历 R 中的向量或列表...因为,我假设您需要我使用 sapply 的每个行元素的索引。
    • @reallybadstatdude 添加了解释并更正了函数中的错字。希望它现在对你有用。
    • @reallybadstatdude 您的预期输出是什么?你能解释一下吗?
    • 是的,获得 5 是预期的输出 :) 目前我必须稍等片刻才能测试我的数据,所以我还不能正确测试人们讨论过的所有不同方法直到我真正得到它(这应该是在接下来的几个小时内......)。此外,在我的声誉进一步提高之前,我不希望接受答案,因为我希望投票给迄今为止回答过的所有人
    【解决方案3】:

    Data.table 解决方案,1 行。

    library(data.table)
    
    dt <- data.table(Index = 1:9,
                     Times = c( '10:30:45.58', '10:30:45.93','10:30:45.104','10:30:45.127','10:30:45.188','10:30:45.188','10:30:45.212','10:30:45.231','10:30:45.231' ),
                     Midquote = c('5.319','5.323','5.325','5.322','5.325',NA,NA,'5.321','5.321')
                    )
    
    > dt[ Times != Times[.N] & !is.na(Midquote), max(Index) ]
    [1] 5
    

    编辑

    要删除索引列,您有(至少)两个选项

    dt2 <- data.table(Times = c( '10:30:45.58', '10:30:45.93','10:30:45.104','10:30:45.127','10:30:45.188','10:30:45.188','10:30:45.212','10:30:45.231','10:30:45.231' ),
                      Midquote = c('5.319','5.323','5.325','5.322','5.325',NA,NA,'5.321','5.321'))
    
    
    # Option 1 - create an id column on the fly (unfortunately data.table recalculate .I after evaluating the "where" clause... so you need to save it)
    dt2[, cbind(.SD, id=.I)][ Times != Times[.N] & !is.na(Midquote), max(id) ]
    
    # Option 2 - simply check the last position of where your condition is met
    dt2[, max(which(Times != Times[.N] & !is.na(Midquote))) ]
    

    NB 你不能这样做 nrow 因为你可以有,比如说,第 1 条,第 2 条和第 4 条记录符合你的条件,而 nrow 会给你 3,这是错误的因为第三行不匹配。

    编辑 2 (选项 3 不正确

    dt3 <- data.table(Times = c( '10:30:45.58', '10:30:45.93','10:30:45.104','10:30:45.127','10:30:45.188','10:30:45.188','10:30:45.212','10:30:45.231','10:30:45.231' ),
                      Midquote = c('5.319','5.323', NA,'5.322','5.325', NA, NA,'5.321','5.321'))
    
    
    # Option 1 - create an id column on the fly (unfortunately data.table recalculate .I after evaluating the "where" clause... so you need to save it)
    dt3[, cbind(.SD, id=.I)][ Times != Times[.N] & !is.na(Midquote), max(id) ]
    [1] 5
    
    # Option 2 - simply check the last position of where your condition is met
    dt3[, max(which(Times != Times[.N] & !is.na(Midquote))) ]
    [1] 5
    
    # Option 3 - good luck with this
    nrow(dt3[Times != Times[.N] & !is.na(Midquote)])
    [1] 4
    

    【讨论】:

    • 这看起来确实很有效,但是有没有办法在不创建新列的情况下做到这一点?另外,如果我错了,请纠正我,但据我所知,该函数似乎在数据表中向前移动,而不是在数据表中向后移动。由于我需要向后移动数据表,这可能不合适(但当然我可能会以错误的方式解释它)
    • 对不起,请忽略我之前的评论,我想我明白你为什么现在使用 max() 函数了。我只是想知道,这是否可以替代您所写的内容: nrow((df2[Times != Times[i] & !is.na(Midquote)])) ?这样我就不需要创建一个新的索引列。请注意,上面Times[i] 代码中的i 仅指一般索引值(因为索引可以更改并且不一定是数据表的最后一个值)
    • 谢谢你,最后一个问题:你提到不能使用nrow,但我不完全理解你的例子是什么意思。对于这里的数据集示例,使用nrow 似乎可以工作(因为它返回 5)所以我想知道如果不是太麻烦的话,你是否可以更简单地解释一下它
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-31
    • 1970-01-01
    • 2017-07-27
    • 1970-01-01
    • 2020-11-05
    • 2022-01-23
    • 1970-01-01
    相关资源
    最近更新 更多