Wybieranie wierszy ramki danych na podstawie częściowego dopasowania ciągu w kolumnie


99

Chcę wybrać wiersze z ramki danych na podstawie częściowego dopasowania ciągu w kolumnie, np. Kolumna „x” zawiera ciąg „hsa”. Korzystanie sqldf- jeśli miałlike składnię - zrobiłbym coś takiego:

select * from <> where x like 'hsa'.

Niestety, sqldf nie obsługuje tej składni.

Lub podobnie:

selectedRows <- df[ , df$x %like% "hsa-"]

Co oczywiście nie działa.

Czy ktoś może mi w tym pomóc?


6
Czy możesz opublikować kilka wierszy swoich danych, najlepiej używając czegoś takiego jak dput(head(conservedData)).
A5C1D2H2I1M1N2O1R2T1

Odpowiedzi:


151

Zauważyłem, że wspomniałeś o funkcji %like%w swoim obecnym podejściu. Nie wiem, czy jest to odniesienie do %like%pliku z „data.table”, ale jeśli tak, zdecydowanie możesz go użyć w następujący sposób.

Zauważ, że obiekt nie musi być a data.table(ale pamiętaj też, że podejścia do podzbiorów dla data.frames i data.tables nie są identyczne):

library(data.table)
mtcars[rownames(mtcars) %like% "Merc", ]
iris[iris$Species %like% "osa", ]

Jeśli tak właśnie było, być może właśnie pomieszałeś pozycje wierszy i kolumn w celu podzbioru danych.


Jeśli nie chcesz ładować pakietu, możesz spróbować użyć polecenia grep()do wyszukania pasującego ciągu. Oto przykład ze mtcarszbiorem danych, w którym dopasowujemy wszystkie wiersze, w których nazwy wierszy zawierają „Merc”:

mtcars[grep("Merc", rownames(mtcars)), ]
             mpg cyl  disp  hp drat   wt qsec vs am gear carb
# Merc 240D   24.4   4 146.7  62 3.69 3.19 20.0  1  0    4    2
# Merc 230    22.8   4 140.8  95 3.92 3.15 22.9  1  0    4    2
# Merc 280    19.2   6 167.6 123 3.92 3.44 18.3  1  0    4    4
# Merc 280C   17.8   6 167.6 123 3.92 3.44 18.9  1  0    4    4
# Merc 450SE  16.4   8 275.8 180 3.07 4.07 17.4  0  0    3    3
# Merc 450SL  17.3   8 275.8 180 3.07 3.73 17.6  0  0    3    3
# Merc 450SLC 15.2   8 275.8 180 3.07 3.78 18.0  0  0    3    3

I kolejny przykład, używając iriszbioru danych wyszukującego ciąg osa:

irisSubset <- iris[grep("osa", iris$Species), ]
head(irisSubset)
#   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 1          5.1         3.5          1.4         0.2  setosa
# 2          4.9         3.0          1.4         0.2  setosa
# 3          4.7         3.2          1.3         0.2  setosa
# 4          4.6         3.1          1.5         0.2  setosa
# 5          5.0         3.6          1.4         0.2  setosa
# 6          5.4         3.9          1.7         0.4  setosa

W przypadku problemu spróbuj:

selectedRows <- conservedData[grep("hsa-", conservedData$miRNA), ]

+1: pamiętaj również, że grepobsługuje wyrażenia regularne, więc ^hsa-zamiast tego możesz użyć grep .
nico

3
@nico: w rzeczywistości greppochodzi z polecenia ed g / re / p (global / regular expression / print) i ujawnia swoją prawdziwą moc tylko mistrzowi wyrażenia regularnego-fu ;-): en.wikipedia.org/ wiki / Grep
Stephan Kolassa

1
% Jak% sugestia jest super! Zalecam umieszczenie tego na początku odpowiedzi.
Aren Cambre

@ArenCambre, gotowe. Może pomoże mi to zdobyć kolejne 11 głosów, abym mógł dostać nową czapkę przed końcem roku :-)
A5C1D2H2I1M1N2O1R2T1

@ A5C1D2H2I1M1N2O1R2T1 Świetna odpowiedź! Czy istnieje sposób na użycie% like% do wyszukania dwóch ciągów, które występują razem (jak „pet” i „pip” występujące w wierszu ramki danych jako „peter piper”)?
nigus21

62

Spróbuj str_detect()z pakietu stringr , który wykrywa obecność lub brak wzorca w ciągu.

Tutaj jest podejście, które również zawiera z %>%rury i filter()z dplyr opakowaniu:

library(stringr)
library(dplyr)

CO2 %>%
  filter(str_detect(Treatment, "non"))

   Plant        Type  Treatment conc uptake
1    Qn1      Quebec nonchilled   95   16.0
2    Qn1      Quebec nonchilled  175   30.4
3    Qn1      Quebec nonchilled  250   34.8
4    Qn1      Quebec nonchilled  350   37.2
5    Qn1      Quebec nonchilled  500   35.3
...

Spowoduje to odfiltrowanie zbioru danych próbki CO2 (dostarczanego z R) pod kątem wierszy, w których zmienna Treatment zawiera podciąg „non”. Możesz dostosować, czy str_detectznajdzie ustalone dopasowania, czy też użyje wyrażenia regularnego - zobacz dokumentację pakietu stringr.


Możesz także użyć funkcji trc_detect w ten sposóbmyDataFrame[str_detect(myDataFrame$key, myKeyPattern),]
Bemipefe

21

LIKE powinien działać w sqlite:

require(sqldf)
df <- data.frame(name = c('bob','robert','peter'),id=c(1,2,3))
sqldf("select * from df where name LIKE '%er%'")
    name id
1 robert  2
2  peter  3

SQLDF najlepiej nadaje się do tworzenia list. Jednak nie może usuwać wierszy.
dr Suat Atan

1
Dlaczego ładuje się require()tutaj pakiet R
rgalbo

Ponieważ nie jest to standardowa biblioteka R i musisz ją ręcznie zainstalować, a następnie załadować za pomocą requirefunkcji.
bartektartanus

0

Inną opcją byłoby po prostu użycie greplfunkcji:

df[grepl('er', df$name), ]
CO2[grepl('non', CO2$Treatment), ]

df <- data.frame(name = c('bob','robert','peter'),
                 id = c(1,2,3)
                 )

# name id
# 2 robert  2
# 3  peter  3
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.