【问题标题】:Replace values in column of a dataframe based on overlap with a vector根据与向量的重叠替换数据框列中的值
【发布时间】:2015-08-15 09:03:20
【问题描述】:

晚上好,

我有一个 150.000 行和 7 列的大型数据框,如下所示

     ID cola colb colc cold cole colf
 XXXYYY    0    0    0    0    0    0
 XXYYXX    0    0    0    0    0    0
 XYXYXY    0    0    0    0    0    0
 YYYXXX    0    0    0    0    0    0
...

我的数据框中还有包含 ID 子集的向量 veca、vecb、vecc、vecd、vece 和 vecf。 我想编写一个循环,在该循环中,我根据数据帧和向量之间 ID 号的重叠将 1 分配给列。 例如,如果veca <- c("XXXYYY", "XXYYXX") 那么输出应该是:

     ID cola colb colc cold cole colf
 XXXYYY    1    0    0    0    0    0
 XXYYXX    1    0    0    0    0    0
 XYXYXY    0    0    0    0    0    0
 YYYXXX    0    0    0    0    0    0
...

...我想对所有列重复这一点。

通常我会这样写:

dataframe$cola[dataframe$ID %in% veca ] <- 1

但是,我在循环中编写上述内容时遇到了麻烦。我尝试了 paste 和 assign 的各种组合,但到目前为止还没有运气。

稍后在我的代码中,我还想根据 ID 号的类似重叠删除数据帧的行(通常写为 dataframe &lt;- dataframe[!(dataframe$ID %in% veca),]),但我认为这与

最后,我要补充一点,我的平台是 x86_64-w64-mingw32,我的 R 版本是 R 版本 3.1.2

非常感谢您的帮助。

【问题讨论】:

    标签: r for-loop replace


    【解决方案1】:

    可以使用row/column索引

    lst <- mget(paste0('vec', letters[1:6]))
    d2 <- stack(lst)
    d1[-1][cbind(match(d2$values, d1$ID),
       match(substr(d2$ind, 4,4), substr(names(d1)[-1], 4,4)))] <- 1
    d1
    #      ID cola colb colc cold cole colf
    #1 XXXYYY    1    0    1    0    1    1
    #2 XXYYXX    1    0    0    0    0    0
    #3 XYXYXY    0    1    0    1    0    1
    #4 YYYXXX    0    0    1    0    0    0
    

    要删除重叠的 ID,

    IDstoremove <- Reduce(`intersect`, lst) #in this example, none
    d1[!(d1$ID %in% IDstoremove),]
    

    数据

    d1 <- structure(list(ID = c("XXXYYY", "XXYYXX", "XYXYXY", "YYYXXX"), 
    cola = c(0L, 0L, 0L, 0L), colb = c(0L, 0L, 0L, 0L), colc = c(0L, 
    0L, 0L, 0L), cold = c(0L, 0L, 0L, 0L), cole = c(0L, 0L, 0L, 
    0L), colf = c(0L, 0L, 0L, 0L)), .Names = c("ID", "cola", 
    "colb", "colc", "cold", "cole", "colf"), class = "data.frame", 
    row.names = c(NA, -4L))
    
    veca<-c("XXXYYY","XXYYXX")
    vecb <- 'XYXYXY'
    vecc <- c('XXXYYY', 'YYYXXX')
    vecd <- 'XYXYXY'
    vece <- 'XXXYYY'
    vecf <- c('XXXYYY', 'XYXYXY')
    

    【讨论】:

    • 索引的好主意。我不怎么用stack,会研究应用。 +1
    • @plafort 谢谢,我认为这里不需要match 部分(因为它是订购的)。在这种情况下,假设顺序相同,我们可以将 lst 的名称设置为 1:7,在stack 之后转换为数字,然后将其用作列索引。
    • 我非常抱歉@akrun,我认为是向量的对象确实是列表。所以 veca 可能是: 1 XXXYYY 2 XXYYXX 这会破坏堆叠。有办法克服吗?
    • @Sigugeir 你是在说veca &lt;- list('XXXYYY', 'XXYYXX')。在这种情况下,您可以取消列出它veca &lt;- unlist(veca); vecb &lt;- unlist(vecb);...,然后相同的代码应该可以工作。
    【解决方案2】:
    #addones
    
    lstcol <- list('cola', 'colb')
    lstvec <- list(veca, vecb)
    
    myfunc <- function(COL, VEC) {
      dataframe[[COL]][dataframe$ID %in% VEC] <<- 1
    }
    
    for(i in 1:length(lstcol)) {
      myfunc(lstcol[[i]], lstvec[[i]])
    }
    
    dataframe
    
    #      ID cola colb colc cold cole colf
    #1 XXXYYY    1    0    0    0    0    0
    #2 XXYYXX    1    0    0    0    0    0
    #3 XYXYXY    0    1    0    0    0    0
    #4 YYYXXX    0    0    0    0    0    0
    
    #remove lines
    
    rowstoremove <- c('YYYXXX')
    dataframe[!dataframe$ID == rowstoremove, ]
    
    #       ID cola colb colc cold cole colf
    # 1 XXXYYY    1    0    0    0    0    0
    # 2 XXYYXX    1    0    0    0    0    0
    # 3 XYXYXY    0    1    0    0    0    0
    

    您可以通过填写完整的 veccol 列表来完成您的完整输出。

    【讨论】:

    • 另一种选择是使用Map,即myfunc &lt;- function(v1, v2){ v1[d1$ID %in% v2] &lt;-1; v1}; d1[-1] &lt;- Map(myfunc, d1[-1], lst) lstd1 来自我的帖子。
    • 谢谢!我正在考虑使用 mapply 来替换那个 for 循环。没有任何效果。我需要该函数通过第 i 个元素遍历 COL 列表和 VEC 列表。所以Map 是正确的。明白了
    • 这似乎是一个很好的解决方案,我非常想申请。我确实在我的问题中犯了一个相当愚蠢的错误,但是我认为是向量的对象确实是列表。您认为您可以使用列表对象 @plafort 提供类似的解决方案吗?非常感谢您,很抱歉给您带来了麻烦。
    • np 在您的问题中添加一个列表示例。
    • 抱歉,我是新用户,我似乎找不到在哪里编辑我的原始问题。以下是我的一个列表的外观示例:列表确实(有点明显)不包含数字,这些数字表示每个 ID 的行(它是一个多行的单列)head(example_list) ID 1 XXXXXX 2 YYYYYX 3 XXXYYY 4 XXYYXX 5 XXXXXY 6 XXXXYY
    【解决方案3】:

    你能发布为什么它不起作用吗?您建议的代码为我生成正确的输出:

        > ## Set up the dataframe d1
        > z4<-rep(0,4) # 4 zeros
        > d1<-data.frame(ID=c("XXXYYY","XXYYXX","XYXYXY","YYYXXX"), cola=z4,colb=z4,colc=z4,cold=z4,cole=z4,colf=z4)
        > veca<-c("XXXYYY","XXYYXX")
        > d1
              ID cola colb colc cold cole colf
        1 XXXYYY    0    0    0    0    0    0
        2 XXYYXX    0    0    0    0    0    0
        3 XYXYXY    0    0    0    0    0    0
        4 YYYXXX    0    0    0    0    0    0
    
        > ## change cola
        > d1$cola[d1$ID %in% veca ] <- 1
        > d1
              ID cola colb colc cold cole colf
        1 XXXYYY    1    0    0    0    0    0
        2 XXYYXX    1    0    0    0    0    0
        3 XYXYXY    0    0    0    0    0    0
        4 YYYXXX    0    0    0    0    0    0
    
        > ## Remove lines
        > d1<-d1[!(d1$ID %in% veca),]
        > d1
              ID cola colb colc cold cole colf
        3 XYXYXY    0    0    0    0    0    0
        4 YYYXXX    0    0    0    0    0    0
    

    【讨论】:

    • 问题询问如何一次循环所有向量vec[a] 和列的过程。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多