R,根据多列中的值删除行

时间:2018-07-26 20:07:44

标签: r dataframe dplyr data-cleaning

假设我有一个包含100行100列的数据框。

对于每一行,如果任意两列具有相同的值,则应删除此行。

例如,如果第1列和第2列相等,则应删除此行。

另一个示例,如果第10列和第47列相等,则也应删除此行。

示例:

test <- data.frame(x1 = c('a', 'a', 'c', 'd'),
               x2 = c('a', 'x', 'f', 'h'),
               x3 = c('s', 'a', 'f', 'g'),
               x4 = c('a', 'x', 'u', 'a'))

test

  x1 x2 x3 x4
1  a  a  s  a
2  a  x  a  x
3  c  f  f  u
4  d  h  g  a

仅应保留第四行。

如何以一种简洁的方式做到这一点?不使用for循环。...

3 个答案:

答案 0 :(得分:2)

在此20x20数据帧上进行了测试

library(tidyverse)    

N <- 20
df <- matrix(as.integer(runif(N^2, 1, 500)), nrow = N, ncol = N) %>% 
  as.tibble()

df

# # A tibble: 20 x 20
# V1    V2    V3    V4    V5    V6    V7    V8    V9   V10   V11   V12   V13   V14   V15   V16   V17   V18   V19   V20
# <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
#   1   350   278   256   484   486   249    35   308   248    66   493   130   149     2   374    51   370   423   165   388
# 2   368   448   441    62   304   373    38   375   406   463   412    95   174   365   170   113   459   369    62    21
# 3   250   459   416   128   372    67   281   450    48   122   308    56   121   497   498   220    34     4   126   411
# 4   171   306   390    13   395   160   256   258    76   131   471   487   190   492    21   237   380   129     5    30
# 5   402   421     6   401    50   292   470   319   283   178   234    46   176   178   288   499     7   221   123   268
# 6   415   342   132   379   150    35   323   225   246   496   460   478   205   255   460    62    78   207    82   118
# 7   207    52   420   216     9   366   390   382   304    63   427   425   350   112   488   400   328   239   148    40
# 8   392   455   156   386   478     3   359   184   420   138    29   434    31   279    87   233   455    21   181   437
# 9   349   460   498   278   104    93   253   287   124   351    60   333   321   116    19   156   372   168    95   169
# 10   386    73   362   127   313    93   427    81   188   366   418   115   353   412   483   147   295    53    82   188
# 11   272   480   168   306   359    75   436   228   187   279   410   388    62   227   415   374   366   313   187    49
# 12   177   382   233   146   338    76   390   232   336   448   175    79   202   230   317   296   410    90   102   465
# 13   108   433    59   151     8   138   464   458   183   316   481   153   403   193    71   136    27   454    62   439
# 14   421    72   106   442   338   440   476   357    74   108    94   407   453   262   355   356    27   217   243   455
# 15   325   449   151   473   241    11   154    52    77   489   137   279   420   120   165   289    70   128   384    53
# 16   126   189    43   354   233   168    48   285   175   348   404   254   168   126    95    65   493   493   187   228
# 17    26   143   112   107   350   198   353   439   192   158   151    23   326     4   304   162    84   412   499   170
# 18    88   156   222   227   452   233   397   203   478    73   483   241   151    38   176    77   244   396     9   393
# 19   361   486   423   310   153   235   274   204   399   493   422   374   399    10   215   468   322    38   395   390
# 20   417   124    21   220   123   399   354   182   233    24   397   263   182   211   360   419   202   240   363   187

删除所有重复的行

df %>% 
  group_by(id = row_number()) %>% 
  gather(col, value, -id) %>% 
  filter(!any(duplicated(value))) %>% 
  spread(col, value)

# # A tibble: 11 x 21
# # Groups:   id [11]
# id    V1   V10   V11   V12   V13   V14   V15   V16   V17   V18   V19    V2   V20    V3    V4    V5    V6    V7    V8    V9
# <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
#   1     1   350    66   493   130   149     2   374    51   370   423   165   278   388   256   484   486   249    35   308   248
# 2     3   250   122   308    56   121   497   498   220    34     4   126   459   411   416   128   372    67   281   450    48
# 3     4   171   131   471   487   190   492    21   237   380   129     5   306    30   390    13   395   160   256   258    76
# 4     7   207    63   427   425   350   112   488   400   328   239   148    52    40   420   216     9   366   390   382   304
# 5     9   349   351    60   333   321   116    19   156   372   168    95   460   169   498   278   104    93   253   287   124
# 6    12   177   448   175    79   202   230   317   296   410    90   102   382   465   233   146   338    76   390   232   336
# 7    13   108   316   481   153   403   193    71   136    27   454    62   433   439    59   151     8   138   464   458   183
# 8    14   421   108    94   407   453   262   355   356    27   217   243    72   455   106   442   338   440   476   357    74
# 9    15   325   489   137   279   420   120   165   289    70   128   384   449    53   151   473   241    11   154    52    77
# 10    17    26   158   151    23   326     4   304   162    84   412   499   143   170   112   107   350   198   353   439   192
# 11    18    88    73   483   241   151    38   176    77   244   396     9   156   393   222   227   452   233   397   203   478

答案 1 :(得分:2)

使用apply在每一行中查找重复项。 (请注意,这会在内部将您的数据转换为矩阵以进行比较。如果您要进行很多按行操作,我建议将其保留为matrix或将其转换为长格式,如Jack Brookes的答案。)

# sample data
set.seed(47)
dd = data.frame(matrix(sample(1:5000, size = 100^2, replace = TRUE), nrow = 100))

# remove rows with duplicate entries
result = dd[apply(dd, MARGIN =  1, FUN = function(x) !any(duplicated(x))), ]

答案 2 :(得分:0)

您可以尝试dplyr中的一系列过滤器。我在这里整理了一些样本数据。如果您的变量被命名,那么您可以使用第一个示例。否则第二个应该工作

library(tidyverse)
#> Warning: package 'dplyr' was built under R version 3.5.1
data <- data_frame(
  A = c(1,2,3,4,5,6),
  B= c(1,3,5,7,9,11),
  C = c(2,2,6,8,10,12)
)

data %>%
  filter(A != B) %>%  # This removed the first row
  filter(A != C) # This removed the second row
#> # A tibble: 4 x 3
#>       A     B     C
#>   <dbl> <dbl> <dbl>
#> 1     3     5     6
#> 2     4     7     8
#> 3     5     9    10
#> 4     6    11    12

data %>% 
  filter(.[1] != .[2]) %>% 
  filter(.[1] != .[3])
#> # A tibble: 4 x 3
#>       A     B     C
#>   <dbl> <dbl> <dbl>
#> 1     3     5     6
#> 2     4     7     8
#> 3     5     9    10
#> 4     6    11    12