找到数据帧对角线上的所有零

时间:2018-05-18 15:02:30

标签: r dplyr

我不知道此问题是否曾被提出过,所以我想继续发布。 我有一个如下所示的数据框:

x <- data.frame(species = c("Alpha", "Alpha", "Alpha","Beta", "Beta", "Beta","Gamma", "Gamma", "Gamma"), lifestage = factor(c("infant", "juvenile", "adult", "infant", "juvenile", "adult", "infant", "juvenile", "adult"),levels = c("infant", "juvenile", "adult")), age = c(10, 20, 30, 11, 21, 31, 9, 19, 29))

ggplot(x, aes(x = reorder(species, -age), y = age, fill = lifestage)) + 
       geom_bar(stat = "identity", position = position_stack(reverse = TRUE)) + 
       coord_flip()

等等5年的数据。每年与75列相关联,条目“C0x”与县代码下的特定“C0x”相关联。基本上它是一种付款人矩阵。

CountyCode下的所有行都是正确的(大约有65个正确的行),而垂直列并不完全正确。有非常具体的县代码(例如,1,2,3,4,6等)。

因为你可以看到C05与C05不匹配,因为它实际上并不存在,并且对角线上有一个中断。因为表格格式是为了让任何人都可以使用它,所以输入值的人显然会犯下重大错误。

唯一的目标是找到对角线上列不正确的所有值并打破对角线。我想把它们除掉。例如,在C05(列)和行C06(根据县法典)下,2012 - 2016年为零。输出可以是这样一个简单的列表:YEAR CountyCode C01 C02 C03 C04 C05 C06 . . . 2012 C01 132 0 3 1 4 9 2012 C02 0 21 0 57 0 0 2012 C03 0 0 56 0 1 1 2012 C04 0 6 0 40 0 26 2012 C06 0 0 1 0 0 0 2012 C07 0 0 1 32 219 6 . . . . . . 2013 C01 220 9 2 4 0 0 2013 C02 0 54 0 62 0 2 2013 C03 0 0 24 0 1 1 2013 C04 0 6 0 224 0 2 2013 C06 0 0 2 0 0 0 2013 C07 0 0 1 37 2 3 所以我可以找到这些异常值并更好地定位它们。

重点是在列中找到错误的县。

PS:每年约有65(行)x 75(列) 虽然我可以手动尝试,但我想对其进行编码以便可以进一步使用

谢谢!

3 个答案:

答案 0 :(得分:3)

使用data.table - 包的可能解决方案:

library(data.table)
setDT(df)

df[, .(cols_not_in_rows = setdiff(names(.SD)[-1], CountyCode),
       rows_not_in_cols = setdiff(CountyCode, names(.SD)[-1]))
   , by = YEAR]

给出:

   YEAR cols_not_in_rows rows_not_in_cols
1: 2012              C05              C07
2: 2013              C05              C07

使用过的数据:

df <- structure(list(YEAR = c(2012L, 2012L, 2012L, 2012L, 2012L, 2012L, 2013L, 2013L, 2013L, 2013L, 2013L, 2013L),
                     CountyCode = c("C01", "C02", "C03", "C04", "C06", "C07", "C01", "C02", "C03", "C04", "C06", "C07"),
                     C01 = c(132L, 0L, 0L, 0L, 0L, 0L, 220L, 0L, 0L, 0L, 0L, 0L),
                     C02 = c(0L, 21L, 0L, 6L, 0L, 0L, 9L, 54L, 0L, 6L, 0L, 0L),
                     C03 = c(3L, 0L, 56L, 0L, 1L, 1L, 2L, 0L, 24L, 0L, 2L, 1L),
                     C04 = c(1L, 57L, 0L, 40L, 0L, 32L, 4L, 62L, 0L, 224L, 0L, 37L),
                     C05 = c(4L, 0L, 1L, 0L, 0L, 219L, 0L, 0L, 1L, 0L, 0L, 2L),
                     C06 = c(9L, 0L, 1L, 26L, 0L, 6L, 0L, 2L, 1L, 2L, 0L, 3L)),
                .Names = c("YEAR", "CountyCode", "C01", "C02", "C03", "C04", "C05", "C06"), class = "data.frame", row.names = c(NA, -12L))

答案 1 :(得分:2)

在基础R中,要查看哪些列不在df$CountyCode中,您可以执行

names(df[,c(-1,-2)])[!(names(df[,c(-1,-2)]) %in% df$CountyCode)]

如果您只想保留df$CountyCode中的列,也许您可​​以执行类似

的操作
library(tidyverse)
correct <- names(df[,c(-1,-2)])[names(df[,c(-1,-2)]) %in% df$CountyCode]
df %>% select(1,2, correct)

答案 2 :(得分:2)

以下是Base R解决方案:

do.call(rbind, lapply(split(df, df$YEAR), function(x){
  Column = as.matrix(x[,-(1:2)])
  Row = x$CountyCode
  data.frame(Column = colnames(Column)[diag(Column) == 0],
             Row = Row[diag(Column) == 0])
}))

<强>结果:

     Column Row
2012    C05 C06
2013    C05 C06

数据:

df <- structure(list(YEAR = c(2012L, 2012L, 2012L, 2012L, 2012L, 2012L, 2013L, 2013L, 2013L, 2013L, 2013L, 2013L),
                     CountyCode = c("C01", "C02", "C03", "C04", "C06", "C07", "C01", "C02", "C03", "C04", "C06", "C07"),
                     C01 = c(132L, 0L, 0L, 0L, 0L, 0L, 220L, 0L, 0L, 0L, 0L, 0L),
                     C02 = c(0L, 21L, 0L, 6L, 0L, 0L, 9L, 54L, 0L, 6L, 0L, 0L),
                     C03 = c(3L, 0L, 56L, 0L, 1L, 1L, 2L, 0L, 24L, 0L, 2L, 1L),
                     C04 = c(1L, 57L, 0L, 40L, 0L, 32L, 4L, 62L, 0L, 224L, 0L, 37L),
                     C05 = c(4L, 0L, 1L, 0L, 0L, 219L, 0L, 0L, 1L, 0L, 0L, 2L),
                     C06 = c(9L, 0L, 1L, 26L, 0L, 6L, 0L, 2L, 1L, 2L, 0L, 3L)),
                .Names = c("YEAR", "CountyCode", "C01", "C02", "C03", "C04", "C05", "C06"), class = "data.frame", row.names = c(NA, -12L))