【问题标题】:Two loops in a list with NA's - R带有 NA 的列表中的两个循环 - R
【发布时间】:2020-03-30 17:32:28
【问题描述】:

假设我有一个数据框 (df),其中每一行都以 NA 结尾。

    > df
    #      [,1] [,2] [,3] [,4] [,5]
    # [1,]    1    7    9    4   NA
    # [2,]    3    6   NA   NA   NA
    # [3,]    1    6    6    4    3
    # [4,]    7    7   NA   NA   NA
    # [5,]    4    3    1    8   NA

我创建了一个列表,每一行都没有 NA'S

nn <-c()
for (i in 1:nrow(df)){
  nn[[i]]<-t(na.omit(t(df[i,])))
}

例如,nn[[1]]={1,7,9,4}。

现在我想确定每对行之间的距离,但只考虑该对的最小观察次数。例如,第一行有 4 个观察值,第三行有 5 个观察值。所以第一行和第三行之间的距离将只考虑前 4 个观察值。我做了这个有效的代码!但这不是自动的:

i <- 1
dd <- c()
for (j in 1:nrow(df)){
  dd[j] <- dist(as.data.frame(rbind(nn[[i]][1:min(lengths(nn[i]),lengths(nn[j]))],nn[[j]][1:min(lengths(nn[i]),lengths(nn[j]))])))
}
dd1 <- dd

使用i&lt;-1,我计算了第 1 行与其余行之间的距离。 R 用这些距离保存 dd1。 如果我做i&lt;-2dd2 &lt;- dd 我会在第二行得到相同的结果,依此类推..

我正在处理的真实数据集要大得多,我想自动执行此操作。我试图让 i 在 1 和 nrow(df) 之间变化并执行类似 dd[i,j] 的操作,但不起作用。 有人可以帮我自动做到这一点吗?

【问题讨论】:

    标签: r loops for-loop row


    【解决方案1】:

    您不应该删除 NA 值,它们在计算距离时会有所帮助。

    所以从你的原始数据开始:

    df
      V1 V2 V3 V4 V5
    1  1  7  9  4 NA
    2  3  6 NA NA NA
    3  1  6  6  4  3
    4  7  7 NA NA NA
    5  4  3  1  8 NA
    

    我们尝试一次性使用dist() 计算所有行之间的距离:

    dst <- as.matrix(dist(df, diag=TRUE, upper=TRUE))
    dst
              1        2        3        4         5
    1  0.000000 3.535534 3.535534 9.486833 11.456439
    2  3.535534 0.000000 3.162278 6.519202  5.000000
    3  3.535534 3.162278 0.000000 9.617692  8.587782
    4  9.486833 6.519202 9.617692 0.000000  7.905694
    5 11.456439 5.000000 8.587782 7.905694  0.000000
    

    现在这些值有点奇怪,不确定这是否是您要寻找的。阅读help(dist)我们看到了这一点:

    如果某些列 在计算欧几里得、曼哈顿、堪培拉或 Minkowski 距离,总和按比例放大 使用的列数。如果所有对都被排除在 计算一个特定的距离,值为'NA'。

    这就是说 - 如果您的数据有 NA,距离会按比例缩放,因此缺失值也会添加到距离中。这使得距离在大小上具有可比性,尽管某些元素具有 NA 值。

    现在,如果您不希望这样,我们必须重新调整这些距离,以便它们不会被缩放。但首先我们需要了解它们是如何缩放的。

    该函数看到,对于某些特定距离,使用了 5 列中的 2 列,而其他列不适用。它的作用是将距离内的总和乘以 5/2,然后取平方根值(根据欧几里得公式)。

    所以我们需要做的是第 1 步 - 获得这些比率,第 2 步 - 取这些比率的平方根值,第 3 步 - 重新调整。

    对于每个距离,我们首先获取用于计算它们的 NA 元素的数量:

    nas <- outer(rowSums(is.na(df)), rowSums(is.na(df)), FUN=pmax)
    nas
         [,1] [,2] [,3] [,4] [,5]
    [1,]    1    3    1    3    1
    [2,]    3    3    3    3    3
    [3,]    1    3    0    3    1
    [4,]    3    3    3    3    3
    [5,]    1    3    1    3    1
    

    现在使用它,我们得到每个距离具有 NA 值的数据部分:

    frac <- (ncol(df)-nas) / ncol(df)
    frac
         [,1] [,2] [,3] [,4] [,5]
    [1,]  0.8  0.4  0.8  0.4  0.8
    [2,]  0.4  0.4  0.4  0.4  0.4
    [3,]  0.8  0.4  1.0  0.4  0.8
    [4,]  0.4  0.4  0.4  0.4  0.4
    [5,]  0.8  0.4  0.8  0.4  0.8
    

    例如,我们看到,对于第 1-2 对,我们有 3 个缺失值和 2 个可用值。所以可用的占整体的40%。

    接下来,我们取这些比率的平方根,并将它们乘以我们得到的距离(那些调整后的距离),以恢复这种缩放:

    res <- dst * sqrt(frac)
    res
              1        2        3        4         5
    1  0.000000 2.236068 3.162278 6.000000 10.246951
    2  2.236068 0.000000 2.000000 4.123106  3.162278
    3  3.162278 2.000000 0.000000 6.082763  7.681146
    4  6.000000 4.123106 6.082763 0.000000  5.000000
    5 10.246951 3.162278 7.681146 5.000000  0.000000
    

    这就是你的结果。所以总结一下:

    dst  <- as.matrix(dist(df, diag=TRUE, upper=TRUE))
    nas  <- outer(rowSums(is.na(df)), rowSums(is.na(df)), FUN=pmax)
    frac <- (ncol(df)-nas) / ncol(df)
    res  <- dst * sqrt(frac)
    

    【讨论】:

    • 我理解你对距离的想法,这很棒。但我的问题更多是关于如何实现 dd1、dd2、dd3 等。自动而不是手动完成
    猜你喜欢
    • 2018-12-27
    • 1970-01-01
    • 2019-03-24
    • 2017-11-15
    • 1970-01-01
    • 2020-11-04
    • 1970-01-01
    • 2017-05-03
    • 2020-04-23
    相关资源
    最近更新 更多