J'ai un ensemble de données avec des numéros d'identification pour les amis et les intimidateurs des répondants.
Je voudrais passer en revue toutes les nominations d'amitié et toutes les nominations d'intimidateurs dans chaque rangée et obtenir un compte du nombre de personnes qu'ils nomment comme les deux. Toute aide serait formidable!
AVOIR DES DONNÉES:
ID friend_1 friend_2 friend_3 bully_1 bully_2 num_both 1 4 12 7 12 15 1 2 8 6 7 18 20 0 3 9 18 1 2 1 1 4 15 7 2 7 13 1 5 1 17 9 17 1 2 6 9 19 20 14 12 0 7 19 12 20 9 12 1 8 7 1 16 2 15 0 9 1 10 12 1 7 1 10 7 11 9 11 7 2
VOULEZ DES DONNÉES:
ID friend_1 friend_2 friend_3 bully_1 bully_2 1 4 12 7 12 15 2 8 6 7 18 20 3 9 18 1 2 1 4 15 7 2 7 13 5 1 17 9 17 1 6 9 19 20 14 12 7 19 12 20 9 12 8 7 1 16 2 15 9 1 10 12 1 7 10 7 11 9 11 7
4 Réponses :
Nous pouvons utiliser apply par ligne et connaître le nombre d'amis communs qui sont présents à la fois dans les colonnes friend et bully XXX
Ou si vous n'êtes pas un grand fan de apply , vous pouvez utiliser sapply avec la même logique
apply(df, 1, function(x) sum(!is.na(intersect(x[friend_cols], x[bully_cols]))))
S'il y a des valeurs NA et que nous voulons les exclure, nous pouvons utilisez is.na et sum
friend_cols <- grep("friend", names(df))
bully_cols <- grep("bully", names(df))
sapply(seq_len(nrow(df)), function(i)
length(intersect(df[i, friend_cols, drop = TRUE], df[i, bully_cols, drop = TRUE])))
#[1] 1 0 1 1 2 0 1 0 1 2
Hey, merci! Je pense que la version d'application est presque là, mais elle compte les NA en rangées où certaines des observations ont moins de nominations que d'autres. Une idée comment puis-je m'assurer que les NA sont ignorés lors du comptage des matchs?
nous pouvons utiliser sum et is.na pour ignorer les correspondances NA . J'ai mis à jour la réponse.
Vous pouvez essayer de comparer chaque colonne intimidateur avec les colonnes d'amis, puis de prendre l'union pour calculer une matrice de correspondances. Pour obtenir votre num_both il vous suffit de rowSum cette matrice de correspondance:
# ID friend_1 friend_2 friend_3 bully_1 bully_2 num_both #1 1 4 12 7 12 15 1 #2 2 8 6 7 18 20 0 #3 3 9 18 1 2 1 1 #4 4 15 7 2 7 13 1 #5 5 1 17 9 17 1 2 #6 6 9 19 20 14 12 0 #7 7 19 12 20 9 12 1 #8 8 7 1 16 2 15 0 #9 9 1 10 12 1 7 1 #10 10 7 11 9 11 7 2
Le lapply calcule les correspondances pour chaque bully puis le Réduire les combine en une seule matrice à additionner sur les lignes.
bully_cols <- grep("bully", names(df))
friend_cols <- grep("friend", names(df))
df$num_both <- rowSums(Reduce("|", lapply(df[,bully_cols], function(x, compare) compare == x, compare = df[,friend_cols])))
En supposant que les valeurs sont uniques au sein des groupes d'amis / intimidateurs, une approche simple serait:
apply(df[,-1], 1, function (x) sum(table(x) > 1)) [1] 1 0 1 1 2 0 1 0 1 2
Voici une approche basée sur Ou en utilisant ou une autre approche en bouclant les lignes avec melt à partir de data.table . Nous fondons dans un format 'long' basé sur les modèles dans les noms de colonne (commencez par ami , intimidateur ) , groupé par 'ID', obtenez la longueur des éléments intersect des longues colonnes de l'ensemble de données 'value1', 'value2' et effectuez une jointure sur code > le 'ID' df1 <- structure(list(ID = 1:10, friend_1 = c(4L, 8L, 9L, 15L, 1L, 9L,
19L, 7L, 1L, 7L), friend_2 = c(12L, 6L, 18L, 7L, 17L, 19L, 12L,
1L, 10L, 11L), friend_3 = c(7L, 7L, 1L, 2L, 9L, 20L, 20L, 16L,
12L, 9L), bully_1 = c(12L, 18L, 2L, 7L, 17L, 14L, 9L, 2L, 1L,
11L), bully_2 = c(15L, 20L, 1L, 13L, 1L, 12L, 12L, 15L, 7L, 7L
)), class = "data.frame", row.names = c(NA, -10L))
tidyverse en rassembler au format 'long', groupé par 'ID' , résumer avec la longueur de intersecter les éléments de «valeur» en fonction de l'occurrence de «ami» ou «intimidateur» dans la clé « 'et right_join avec l'ensemble de données d'origine df1 %>%
mutate(num_both = pmap(.[-1], ~ c(...) %>%
{length(intersect(.[1:3], .[4:5]))}))
pmap library(tidyverse)
df1 %>%
gather(key, value, -ID) %>%
group_by(ID) %>%
summarise(num_both = length(intersect(value[str_detect(key, 'friend')],
value[str_detect(key, 'bully')]))) %>%
right_join(df1)
# A tibble: 10 x 7
# ID num_both friend_1 friend_2 friend_3 bully_1 bully_2
# <int> <int> <int> <int> <int> <int> <int>
# 1 1 1 4 12 7 12 15
# 2 2 0 8 6 7 18 20
# 3 3 1 9 18 1 2 1
# 4 4 1 15 7 2 7 13
# 5 5 2 1 17 9 17 1
# 6 6 0 9 19 20 14 12
# 7 7 1 19 12 20 9 12
# 8 8 0 7 1 16 2 15
# 9 9 1 1 10 12 1 7
#10 10 2 7 11 9 11 7
données
library(data.table)
setDT(df1)[melt(df1, measure = patterns('^friend', '^bully'))[,
.(num_both = length(intersect(value1, value2))), ID], on = .(ID)]
# ID friend_1 friend_2 friend_3 bully_1 bully_2 num_both
# 1: 1 4 12 7 12 15 1
# 2: 2 8 6 7 18 20 0
# 3: 3 9 18 1 2 1 1
# 4: 4 15 7 2 7 13 1
# 5: 5 1 17 9 17 1 2
# 6: 6 9 19 20 14 12 0
# 7: 7 19 12 20 9 12 1
# 8: 8 7 1 16 2 15 0
# 9: 9 1 10 12 1 7 1
#10: 10 7 11 9 11 7 2