mit:
df[rowSums(is.na(df[,3:10]) * !is.na(df[,4:11])) > 0,]
Sie erhalten:
id dx dia01 dia02 dia03 dia04 dia05 dia06 dia07 dia08 dia09
a 1 S06.4 6.7 7 6.5 7 7.2 <NA> <NA> 6.6 6.7
b 2 S06.2 5 <NA> 4.9 7.8 9.3 8 7.8 8 <NA>
c 3 S06.5 7 5.5 <NA> <NA> 7.2 8 7.6 <NA> 6.7
Was das bedeutet:
is.na(df[,3:10])
überprüfen, welcher der Werte in den Spalten dia01
bis dia08
NA
ist und gibt eine logische Matrix zurück.
!is.na(df[,4:11])
macht das gleiche für die nächsten Werte in jeder Reihe der df[,3:10]
und gibt auch eine logische Matrix
- diese beiden Matrizen Multipliziert man gibt eine logische Matrix für die erforderliche Bedingung.
- Mit
rowSums
überprüfen Sie in jeder Zeile mindestens einmal, ob die Bedingungen erfüllt sind.
Als Antwort auf Ihren Kommentar: Wenn Sie durch einen numerischen Wert gefolgt, um sicherzustellen, wollen die NA
, Sie obige Lösung verändern könnten:
# first convert the 'dia*''-columns to numeric
df[-c(1,2)] <- lapply(df[-c(1,2)], function(x) as.numeric(as.character(x)))
# then do the same because values that can't converted to numeric will give NA
df[rowSums(is.na(df[,3:10]) * !is.na(df[,4:11])) > 0,]
oder ohne numerische konvertieren zuerst:
df[rowSums(is.na(df[,3:10]) * !is.na(sapply(df[4:11], function(x) as.numeric(as.character(x))))) > 0,]
HINWEIS:
Mit der Methode, die Sie zum Erstellen Ihrer Beispieldaten verwendet haben, werden Sie mit allen Faktorspalten enden. Ich nehme an, du willst das nicht.
A möglicherweise korrekt formatiert Beispiel-Datensatz wäre:
df <- structure(list(id = c("1", "2", "3", "4", "5"),
dx = c("S06.4", "S06.2", "S06.5", "S06.5", "S06.1"),
dia01 = c(6.7, 5, 7, 7, 6.7),
dia02 = c(7, NA, 5.5, 7, NA),
dia03 = c(6.5, 4.9, NA, 7, NA),
dia04 = c(7, 7.8, NA, 6.9, NA),
dia05 = c(7.2, 9.3, 7.2, 6.8, NA),
dia06 = c(NA, 8, 8, 9, NA),
dia07 = c(NA, 7.8, 7.6, 6, NA),
dia08 = c(6.6, 8, NA, 6.6, NA),
dia09 = c(6.7, NA, 6.7, 6.7, NA)),
.Names = c("id", "dx", "dia01", "dia02", "dia03", "dia04", "dia05", "dia06", "dia07", "dia08", "dia09"),
row.names = c("a", "b", "c", "d", "e"),
class = "data.frame")
Das vorgeschlagene Verfahren auf das so gut funktioniert.
Wie in den Kommentaren von @Frank erwähnt, ist es meist besser sind Ihre Daten im langen Format zu speichern. Mit:
library(data.table)
setDT(df)[, 3:11 := lapply(.SD, function(x) as.numeric(as.character(x))), .SDcols = 3:11][]
melt(df, id = 1:2)[, if(any(is.na(value) & !is.na(shift(value, type = 'lead')))) .SD, by = .(id, dx)]
Sie erhalten:
id dx variable value
1: 1 S06.4 dia01 6.7
2: 1 S06.4 dia02 7.0
3: 1 S06.4 dia03 6.5
4: 1 S06.4 dia04 7.0
5: 1 S06.4 dia05 7.2
6: 1 S06.4 dia06 NA
7: 1 S06.4 dia07 NA
8: 1 S06.4 dia08 6.6
9: 1 S06.4 dia09 6.7
10: 2 S06.2 dia01 5.0
11: 2 S06.2 dia02 NA
12: 2 S06.2 dia03 4.9
13: 2 S06.2 dia04 7.8
14: 2 S06.2 dia05 9.3
15: 2 S06.2 dia06 8.0
16: 2 S06.2 dia07 7.8
17: 2 S06.2 dia08 8.0
18: 2 S06.2 dia09 NA
19: 3 S06.5 dia01 7.0
20: 3 S06.5 dia02 5.5
21: 3 S06.5 dia03 NA
22: 3 S06.5 dia04 NA
23: 3 S06.5 dia05 7.2
24: 3 S06.5 dia06 8.0
25: 3 S06.5 dia07 7.6
26: 3 S06.5 dia08 NA
27: 3 S06.5 dia09 6.7
Eine weitere Alternative ist:
setDT(df)[, 3:11 := lapply(.SD, function(x) as.numeric(as.character(x))), .SDcols = 3:11][]
df[unique(melt(df, id = 1:2)[, .I[is.na(value) & !is.na(shift(value, type = 'lead'))], by = .(id, dx)], by = 'id')[,'id'], on = 'id']
Das Ergebnis dieses Ansatzes im Wide-Format jedoch nach wie vor, wie im ersten Teil dieser Antwort dargestellt ist .
Ich versuche Ihr Problem zu verstehen. Also ist die letzte Reihe nicht das, wonach du suchst, oder? –
Was ich brauche ist, die Zeilen zu identifizieren, die eine Sequenz wie c (, any_value) in irgendeiner Spalte entsprechen. In diesem df würden die Zeilen 1, 2 und 3 mit dieser Sequenz übereinstimmen. –
ezequielm