Je pense que la réponse est assez évidente: écrivez directement à d1. C'est la même chose que d2; la sortie sera envoyée plus ou moins directement au client. Il peut ou non être mis en mémoire tampon pendant un moment, mais à moins que la mise en mémoire tampon de sortie explicite soit activée ou que votre serveur Web ait une mémoire tampon ridiculement grande, il l'enverra directement. "Envoyer un fichier" (vraisemblablement via {{X2}}) ferait passer les données dans le même tampon de sortie, mais serait beaucoup plus compliqué et sujet aux erreurs.

x   y  z
10  10 7
10  12 6
11  10 8
11  12 2
12  10 1
12  12 5

x  y  z
10 10 100
11 10 200
12 12 400

Je veux quelque chose comme:

x   y  z
10  10 100
10  12 6
11  10 200
11  12 2
12  10 1
12  12 400

Je suis vraiment désolé pour la question triviale, je n'ai pas pu obtenir la réponse.

4
Pankaj 23 déc. 2015 à 17:58

4 réponses

Meilleure réponse

D'après votre description, je comprends que vous souhaitez remplacer les valeurs z dans d1 par les valeurs z dans d2 lorsque x & amp; y match.

En utilisant la base R:

d3 <- merge(d1, d2, by = c("x","y"), all.x = TRUE)
d3[is.na(d3$z.y),"z.y"] <- d3[is.na(d3$z.y),"z.x"]
d3 <- d3[,-3]
names(d3)[3] <- "z"

Qui donne:

> d3
   x  y   z
1 10 10 100
2 10 12   6
3 11 10 200
4 11 12   2
5 12 10   1
6 12 12 400

Depuis la version 0.5.0, vous pouvez également utiliser le {{X0} } -fonction pour cela (merci à Laurent Hostert pour l'amener à mon attention):

library(data.table)

setDT(d1) # convert the data.frame to a data.table
setDT(d2) # idem

# join the two data.table's and replace the values
d1[d2, on = .(x, y), z := i.z]

Ou en une seule fois:

setDT(d1)[setDT(d2), on = .(x, y), z := i.z]

Qui donne:

> d1
    x  y   z
1: 10 10 100
2: 10 12   6
3: 11 10 200
4: 11 12   2
5: 12 10   1
6: 12 12 400

En utilisant le package dplyr :

d3 <- left_join(d1, d2, by = c("x","y")) %>%
  mutate(z.y = ifelse(is.na(z.y), z.x, z.y)) %>%
  select(-z.x) %>%
  rename(z = z.y)

J'ai deux trames de données coalesce et {{X1}} respectivement comme:

d3 <- left_join(d1, d2, by = c("x","y")) %>% 
  mutate(z = coalesce(z.y, z.x)) %>% 
  select(-c(z.x, z.y))
9
Jaap 4 mai 2020 à 13:26

En plus de l'excellente réponse @Jaap wrt data.table

Dans data.table, vous pouvez vous joindre à l'aide de clés, et avec data.table, tout ce qui est fait via l'utilisation de clés est l'option la plus rapide. Vous pouvez même avoir des noms de colonnes différents, voir l'exemple modifié ci-dessous.

Le long des lignes, les données:

x  y  z
10 10 100
11 10 200
12 12 400

x  q  z
10  10 7
10  12 6
11  10 8
11  12 2
12  10 1
12  12 5

Et code:

library(data.table)

d1 <- fread("d1.csv", sep=" ")
d2 <- fread("d2.csv", sep=" ")

# here is data.table keys magic
# note different column names
setkey(d1, x, q)
setkey(d2, x, y)

q <- d2[d1][is.na(z), z := i.z][, i.z := NULL]

print(q)

Résultat:

    x  y   z
1: 10 10 100
2: 10 12   6
3: 11 10 200
4: 11 12   2
5: 12 10   1
6: 12 12 400
3
h3rm4n 20 janv. 2018 à 17:05

Il semble que vous vouliez vous assurer qu'il n'y a qu'une seule valeur z pour chaque valeur x et y. La question principale est de savoir comment choisir la valeur z à associer. D'après la description, je suppose que vous voulez que la deuxième trame de données soit toujours remplacée, ou que vous voulez que la valeur maximale soit prise.

Commencez par les données brutes:

df1 <- structure(list(x = c(10L, 10L, 11L, 11L, 12L, 12L), y = c(10L, 12L, 10L, 12L, 10L, 12L), z = c(7L, 6L, 8L, 2L, 1L, 5L)), .Names = c("x", "y", "z"), class = "data.frame", row.names = c(NA, -6L))
df2 <- structure(list(x = 10:12, y = c(10L, 10L, 12L), z = c(100L, 200L,400L)), .Names = c("x", "y", "z"), class = "data.frame", row.names = c(NA,-3L))

Si c'est le maximum que vous voulez, alors vous voudrez probablement simplement combiner les deux images, puis extraire le maximum pour chaque x et y:

merged.df <- aggregate(z ~ x + y, data = rbind(df1, df2), max)

Si, à la place, vous voulez que la deuxième trame de données remplace la première, vous agrégerez en utilisant la dernière valeur à correspondre

merged.df <- aggregate(z ~ x+ y, data=rbind(df1, df2), function(d) tail(d, n=1))

Si vous avez plusieurs colonnes en plus de z, alors je ne peux que supposer que vous voulez ce dernier comportement. Pour cela, il vaut mieux utiliser une bibliothèque comme data.table ou dplyr. Dans dplyr, cela ressemblerait à ceci

require(dplyr)
merged.df <- rbind(df1, df2) %>% group_by(x, y) %>% summarise_each(funs(last))

Avec data.table, cela ressemblerait à

require(data.table)
merged.df <- setDT(rbind(df1, df2))[, lapply(.SD, last), .(x,y)]
1
user295691 23 déc. 2015 à 15:26

Vous pouvez également utiliser merge cette update-join dans base en utilisant match et which pour trouver les index utilisés pour sous-paramétrer les tables et interaction pour créer un vecteur clé sur deux.

De cette manière, ni la commande ni la taille de d1 ne seront modifiées. Dans le cas où une clé dans d2 est représentée deux fois, la première occurrence sera utilisée pour mettre à jour d1.

d1 <- read.table(header=TRUE, text="x   y  z
10  10 7
10  12 6
11  10 8
11  12 2
12  10 1
12  12 5")
d2 <- read.table(header=TRUE, text="x  y  z
10 10 100
11 10 200
12 12 400")

key <- c("x", "y") #define which columns are used as matching key
idx <- match(interaction(d2[key]), interaction(d1[key])) #find where it matches
d1$z[idx] <- d2$z #make the update

d1 #show result
#   x  y   z
#1 10 10 100
#2 10 12   6
#3 11 10 200
#4 11 12   2
#5 12 10   1
#6 12 12 400

Alternativement, vous pouvez vérifier s'il y avait une correspondance entre d1 et d2 comme:

idx <- match(interaction(d1[key]), interaction(d2[key]))
idxn <- which(!is.na(idx)) #find where it does not match
d1$z[idxn] <- d2$z[idx[idxn]]

Ou

idx <- match(interaction(d2[key]), interaction(d1[key]))
idxn <- which(!is.na(idx))
d1$z[idx[idxn]] <- d2$z[idxn]
0
GKi 15 juil. 2019 à 11:34