1
votes

comment écrire du code R pour supprimer les lignes en double où une observation est la valeur négative du doublon?

J'ai des données de vente où les erreurs enregistrées au point de vente sont corrigées par la suite et le jeu de données contient toujours des enregistrements pour l'erreur initiale puis un double de l'erreur mais avec une valeur de prix négative. Comment puis-je supprimer ces observations de manière conditionnelle afin que «si prix Les données sont structurées comme p >

Date      Type     Weight     Price
5/5/16    A        15         34
5/5/16    A        15         -34
5/5/16    B        15         43

Un autre problème est que non seulement les erreurs expurgées existent en tant que doublons, mais que les entrées de type, de poids et de prix ont plusieurs doublons valides. par exemple. une vente peut être faite à la même date pour 10 articles de type A à 15 livres chacun pour 34 dollars. - J'ai ajouté une colonne pour compter le nombre de doublons des valeurs absolues test2 % dplyr :: group_by (Date, Type, Weight, ABS_Price)%>% dplyr :: mutate (replicate = seq (n () )) alors comment coderais-je 'si une observation a Price


6 commentaires

La logique ici peut-elle simplement être, si Price <0, supprimez la ligne ?


Je pense qu'ils veulent supprimer les première et deuxième lignes: la ligne avec un prix négatif signifie que la ligne correspondante est une erreur et doit être supprimée


oui, les lignes positives et négatives doivent être supprimées


Bienvenue dans Stack Overflow! Il semble que vous nous demandez d'écrire du code pour vous, ou d'écrire un tutoriel expliquant comment le faire, mais les deux sont hors sujet. Nous devons savoir ce que vous avez essayé et pourquoi cela n'a pas fonctionné.


Vous pouvez envisager de renommer la question en quelque chose comme "Supprimer les lignes qui ont des doublons inexacts". Je pense que ce titre sera plus facile à trouver.


Un autre problème est non seulement que les erreurs expurgées existent sous forme de doublons, mais que les entrées de type, de poids et de prix ont plusieurs doublons valides. par exemple. une vente peut être faite à la même date pour 10 articles de type A à 15 livres chacun pour 34 dollars. - J'ai ajouté une colonne pour compter le nombre de doublons des valeurs absolues test2 <- test%>% dplyr :: group_by (Date, Type, Weight, ABS_Price)%>% dplyr :: mutate (replicate = seq (n () )) alors comment coderais-je `` si une observation a Price <0 puis supprimer l'observation où replicate = x-1 ''


4 Réponses :


1
votes

J'ai ajouté une ligne supplémentaire à votre exemple pour détecter le cas limite probable de deux transactions avec des clés correspondantes - nous ne voulons probablement supprimer que la première correspondance.

library(dplyr)
df2 <- df %>%
  group_by(Date, Type, Weight, Price) %>%
  mutate(repeat_count = row_number()) %>%
  ungroup()

left_join(df2,
          df2 %>% mutate(Price = -Price, cut_flag = FALSE)) %>%
  filter(is.na(cut_flag)) %>%
  select(-cut_flag)

# A tibble: 2 x 5
  Date   Type  Weight Price repeat_count
  <chr>  <chr>  <int> <int>        <int>
1 5/5/16 A         15    34            2
2 5/5/16 B         15    43            1

Mon approche consiste à rechercher des correspondances où tout est identique (y compris le # de la transaction avec ces valeurs de clé) mais le prix est inversé. Si tel est le cas, coupez:

df <- read.table(
  header = T, 
  stringsAsFactors = F,
  text = "Date      Type     Weight     Price
5/5/16    A        15         34
5/5/16    A        15         34
5/5/16    A        15         -34
5/5/16    B        15         43")


0 commentaires

2
votes

Une solution simple de dplyr . Regroupez les lignes par une combinaison de clés qui définissent un doublon (notez que nous pouvons appliquer des transformations aux colonnes à la volée) et filtrez les groupes de singleton.

    Date Type Weight Price abs(Price)
1 5/5/16    B     15    43         43

Tester les données.

Date,Type,Weight,Price
5/5/16,A,15,34
5/5/16,A,15,-34
5/5/16,B,15,43

Sortie de test

library(dplyr)

with.dups <- read.csv(...)
without.dups <- with.dups %>% 
    group_by(Date, Type, Weight, abs(Price)) %>% 
    filter(n()==1) %>%
    as.data.frame  # you can omit this part if you don't need to transform the resulting tibble table to a vanilla data.frame


0 commentaires

0
votes

Nous pouvons le faire dans la base R en utilisant dupliqué . Utilisation des données de @Jon Spring

df[!((duplicated(df[c("Date", "Type", "Weight")]) | 
      duplicated(df[c("Date", "Type", "Weight")], fromLast = TRUE)) & 
      (duplicated(abs(df$Price)) | duplicated(abs(df$Price), fromLast = TRUE))), ]

Cela suppose que vous ayez Date , Type et Weight dans la colonne 1: 3 respectivement. Si leur position n'est pas fixe, vous pouvez également les sélectionner par leur nom

df[!((duplicated(df[1:3]) | duplicated(df[1:3], fromLast = TRUE)) & 
     (duplicated(abs(df$Price)) | duplicated(abs(df$Price), fromLast = TRUE))), ]

#    Date Type Weight Price
#4 5/5/16    B     15    43


0 commentaires

0
votes

légèrement différent de Ronak mais prémisse similaire en utilisant which()

df$price <- abs(df$price)  #take absolute value, making all entries positive

dups <- which(duplicated(df)) #find place of duplicates, where all columns match


newdf <- df[-c(dups-1,dups),] 

Tous les cas en double supprimés et cas immédiat avant chaque duplicata également


3 commentaires

Cela ne fonctionne que si les doublons se succèdent. Si un tel ordre ne peut être garanti, vous devez trier les lignes au préalable. De plus, vous avez écrasé une colonne existante.


L'exemple de code suggère qu'un tel ordre peut exister: Ma réponse s'applique quand c'est le cas, comme je l'ai spécifié. À chacun son avis sur l'écrasement des colonnes existantes pour ce qui a du sens pour son propre code.


Je pense simplement que les deux choses sont suffisamment importantes pour être soulignées dans votre réponse.