从行值中删除重复项

3

我有一个尺寸为58000*900的数据框,其中行值存在重复,我想遍历每一行并将它们删除。下面举个例子来更清楚地说明。

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))

3
请使用dput()函数输出您的数据框df - mtoto
澄清一下,您想删除没有逗号或句点的行,然后从这些行中删除重复内容。 - lmo
@lmo:是的,你说得对。 - Newbie
@mtoto:我已经编辑了这个问题。 - Newbie
3个回答

4

首先,我们使用 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

它可以工作,但是会出现“警告信息:度量变量的属性不相同,它们将被删除”。我在这个错误(https://dev59.com/K14b5IYBdhLWcg3wiiV4)上进行了搜索,但是无法理解原因!! - Newbie
在创建结果中的“value”列时,可以安全地忽略此警告,它只是将每个因子强制转换为字符并丢弃其属性。 - Steven Beaupré

1

这里是一个基于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来选择正确的列,并删除每个字符串中逗号后面的部分。

1

在基本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

这个想法是保留每个项目中第一个逗号前的第一个元素。
缺点是它会保留没有小数值的行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接