【问题标题】:remove duplicates from values in the rows从行中的值中删除重复项
【发布时间】:2016-09-24 12:35:31
【问题描述】:

我有一个尺寸为 58000*900 的 df,其中包含行值中的重复,我想遍历每一行并删除它们。举个例子会更清楚。

df
IDs Name    col1    col2    col3
123 AB.C    1.3,1.3,1.3,1.3,1.3 0,0,0,0,0   5,5,5,5,5
234 CD-E    2,2,2,2,2   0.3,0.3,0.3,0.3,0.3 1,1,1,1,1
568 GHJ 123456      123456              123456
345 FGH 9,9,9,9,9   54,54,54,54,54  0,0,0,0,0

显然每个值都被复制了 5 次,在某些情况下,它们的问题是没有 ., 分隔这些值。 我想要的是删除那些不包含., 的行,其余的删除重复的值。因此,输出将是:

IDs Name    col1    col2    col3
123 AB.C    1.3 0   5
234 CD-E    2   0.3 1
345 FGH 9   54  0

dput(df)
structure(list(IDs = c(123L, 234L, 568L, 345L), Name = structure(c(1L, 
2L, 4L, 3L), .Label = c("ABC", "CDE", "FGH", "GHJ"), class = "factor"), 
    col1 = structure(c(2L, 3L, 1L, 4L), .Label = c("123456", 
    "1.3,1.3,1.3,1.3,1.3", "2,2,2,2,2", "9,9,9,9,9"), class = "factor"), 
    col2 = structure(1:4, .Label = c("0,0,0,0,0", "0.3,0.3,0.3,0.3,0.3", 
    "123456", "54,54,54,54,54"), class = "factor"), col3 = structure(c(4L, 
    2L, 3L, 1L), .Label = c("0,0,0,0,0", "1,1,1,1,1", "123456", 
    "5,5,5,5,5"), class = "factor")), .Names = c("IDs", "Name", 
"col1", "col2", "col3"), class = "data.frame", row.names = c(NA, 
-4L))

【问题讨论】:

  • 可以请dput()你的df吗?
  • 为了澄清,您想删除没有,. 的行,然后从行中删除重复。
  • @lmo: 是的,你是对的
  • @mtoto:我已经编辑了问题。

标签: r dataframe duplicates


【解决方案1】:

首先,我们使用gather() 以长格式重组您的数据,然后我们使用grepl()value 重组您的数据,而没有,。然后,我们使用strsplit()value 中的字符串拆分为一个列表,并使用unnest() 使列表中的每个元素成为自己的行。我们使用distinct()spread() 删除重复的行,将keyvalues 移回列。

library(dplyr)
library(tidyr)

df %>%
  gather(key, value, -(IDs:Name)) %>%
  filter(grepl(",", value)) %>%
  mutate(value = strsplit(value, ",")) %>%
  unnest(value) %>%
  distinct %>%
  spread(key, value)

这给出了:

#Source: local data frame [3 x 5]
#
#    IDs   Name  col1  col2  col3
#  (int) (fctr) (chr) (chr) (chr)
#1   123   AB.C   1.3     0     5
#2   234   CD-E     2   0.3     1
#3   345    FGH     9    54     0

另一个想法是使用splitstackshape中的cSplit

df %>%
  cSplit(., c("col1", "col2", "col3"), direction = "long", sep = ",") %>%
  group_by(Name) %>%
  filter(!any(is.na(.))) %>%
  distinct

这给出了:

#Source: local data table [3 x 5]
#Groups: Name
#
#    IDs   Name  col1  col2  col3
#  (int) (fctr) (dbl) (dbl) (int)
#1   123   AB.C   1.3   0.0     5
#2   234   CD-E   2.0   0.3     1
#3   345    FGH   9.0  54.0     0

【讨论】:

  • 它有效,但给出了Warning message: attributes are not identical across measure variables; they will be dropped。我搜索了这个错误(stackoverflow.com/questions/28972386/…)但无法理解原因!
  • 您可以放心地忽略此警告,它只是将每个因素强制转换为字符并在结果中创建 value 列时删除它们的属性。
【解决方案2】:

这是适用于您的示例数据的基本 R 方法:

df <- read.table(header=T, text="IDs Name    col1    col2    col3
 123 ABC 1.3,1.3,1.3,1.3,1.3 0,0,0,0,0   5,5,5,5,5
                  234 CDE 2,2,2,2,2   0.3,0.3,0.3,0.3,0.3 1,1,1,1,1
                  568 GHJ 123456      123456              123456
                  345 FGH 9,9,9,9,9   54,54,54,54,54  0,0,0,0,0")

# drop rows with no comma or dot
df <- df[-grep("[,.]", df$col1, invert=T),]

df[,grep("^col", names(df))] <- sapply(df[,grep("^col", names(df))], 
                                       function(i) gsub("^([0-9.]+),.*", "\\1", i))

返回

  IDs Name   col1   col2   col3
1 123  ABC    1.3      0      5
2 234  CDE      2    0.3      1
3 568  GHJ 123456 123456 123456
4 345  FGH      9     54      0

我们使用正则表达式函数grepgsub 来选择正确的列并删除每个字符串中逗号后的部分。

【讨论】:

    【解决方案3】:

    基础 R 中的长 apply 方式:

    as.data.frame( apply( df, c(1,2), gsub, pattern="(\\d*[.]*\\d*),.*", replacement="\\1") )
    

    这给出了:

      IDs Name   col1   col2   col3
    1 123  ABC    1.3      0      5
    2 234  CDE      2    0.3      1
    3 568  GHJ 123456 123456 123456
    4 345  FGH      9     54      0
    

    这个想法是只保留每个项目的第一个逗号之前的第一个元素

    缺点 (?) 它保留没有十进制值的行。

    【讨论】:

      猜你喜欢
      • 2018-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-11
      • 1970-01-01
      • 2019-08-08
      相关资源
      最近更新 更多