Konwertuj dane.ramka kolumny od czynników do znaków
Mam ramkę danych. Nazwijmy go bob
:
> head(bob)
phenotype exclusion
GSM399350 3- 4- 8- 25- 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399351 3- 4- 8- 25- 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399352 3- 4- 8- 25- 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399353 3- 4- 8- 25+ 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399354 3- 4- 8- 25+ 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
GSM399355 3- 4- 8- 25+ 44+ 11b- 11c- 19- NK1.1- Gr1- TER119-
Chciałbym połączyć wiersze tej ramki danych (to będzie kolejne pytanie). Ale spójrz:
> class(bob$phenotype)
[1] "factor"
Bob
'kolumny s są czynnikami. Na przykład:
> as.character(head(bob))
[1] "c(3, 3, 3, 6, 6, 6)" "c(3, 3, 3, 3, 3, 3)"
[3] "c(29, 29, 29, 30, 30, 30)"
Nie zaczynam tego rozumieć, ale myślę, że są to wskaźniki do poziomów czynników kolumn (dworu króla caractacusa) bob
? Nie tego mi trzeba.
O dziwo mogę przejść przez kolumny bob
przez hand, and do
bob$phenotype <- as.character(bob$phenotype)
Co działa dobrze. Po jakimś wpisaniu mogę uzyskać dane.ramka, której kolumny są znakami, a nie czynnikami. Więc moje pytanie brzmi: Jak mogę to zrobić automatycznie? Jak przekonwertować dane.ramka z kolumnami współczynników w dane.ramka z kolumnami znakowymi bez konieczności ręcznego przechodzenia przez każdą kolumnę?
Pytanie dodatkowe: dlaczego podejście ręczne działa?
18 answers
Śledzę Matta i Dirka. Jeśli chcesz odtworzyć istniejącą ramkę danych bez zmiany opcji global, możesz ją odtworzyć za pomocą instrukcji apply:
bob <- data.frame(lapply(bob, as.character), stringsAsFactors=FALSE)
To przekonwertuje wszystkie zmienne do klasy "character" , jeśli chcesz konwertować tylko czynniki, patrz Rozwiązanie Marka poniżej .
Jak podkreśla @ hadley, poniżej jest bardziej zwięzła.
bob[] <- lapply(bob, as.character)
W obu przypadkach lapply
wypisuje listę; jednak ze względu na magiczne właściwości R, użycie []
w drugim przypadku przechowuje dane.Klasa frame obiektu bob
, eliminując w ten sposób konieczność konwersji z powrotem na dane.frame używając {[5] } z argumentem stringsAsFactors = FALSE
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:25
Aby zastąpić tylko czynniki:
i <- sapply(bob, is.factor)
bob[i] <- lapply(bob[i], as.character)
W pakiecie dplyr w wersji 0.5.0 wprowadzono nową funkcję mutate_if
:
library(dplyr)
bob %>% mutate_if(is.factor, as.character) -> bob
...i w wersji 1.0.0 została zastąpiona przez across
:
library(dplyr)
bob %>% mutate(across(where(is.factor), as.character)) -> bob
Pakiet purrr z RStudio daje inną alternatywę:
library(purrr)
bob %>% modify_if(is.factor, as.character) -> bob
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-08-20 10:13:49
Opcja globalna
StringsAsFactors: Domyślne ustawienie argumentów danych.kadruj i czytaj.stolik.
Może to być coś, co chcesz ustawić na FALSE
w plikach startowych (np. ~/.Rprofile). Zobacz help(options)
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-06 12:15:21
Jeśli rozumiesz, jak przechowywane są czynniki, możesz uniknąć korzystania z funkcji opartych na zastosowaniach w celu osiągnięcia tego celu. Co wcale nie oznacza, że zastosowane rozwiązania nie działają dobrze.
Czynniki są strukturyzowane jako wskaźniki numeryczne powiązane z listą 'poziomów'. Można to zobaczyć, jeśli przekonwertujesz Współczynnik na liczbę. Więc:
> fact <- as.factor(c("a","b","a","d")
> fact
[1] a b a d
Levels: a b d
> as.numeric(fact)
[1] 1 2 1 3
Liczby zwrócone w ostatnim wierszu odpowiadają poziomom czynnika.
> levels(fact)
[1] "a" "b" "d"
Zauważ, że levels()
zwraca tablicę znaków. Możesz użyć ten fakt, aby łatwo i zwięźle konwertować współczynniki na ciągi lub cyfry, jak to:
> fact_character <- levels(fact)[as.numeric(fact)]
> fact_character
[1] "a" "b" "a" "d"
Działa to również dla wartości liczbowych, pod warunkiem, że zawiniesz swoje wyrażenie w as.numeric()
.
> num_fact <- factor(c(1,2,3,6,5,4))
> num_fact
[1] 1 2 3 6 5 4
Levels: 1 2 3 4 5 6
> num_num <- as.numeric(levels(num_fact)[as.numeric(num_fact)])
> num_num
[1] 1 2 3 6 5 4
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-03-19 05:02:54
Jeśli chcesz, aby nowa ramka danych bobc
Gdzie każdy wektor czynnika W bobf
został przekonwertowany na wektor znakowy, spróbuj tego:
bobc <- rapply(bobf, as.character, classes="factor", how="replace")
Jeśli następnie chcesz przekonwertować go z powrotem, możesz utworzyć logiczny wektor, którego kolumny są czynnikami i użyć go do selektywnego zastosowania współczynnika
f <- sapply(bobf, class) == "factor"
bobc[,f] <- lapply(bobc[,f], factor)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-05 07:37:05
Zazwyczaj wykonuję tę funkcję niezależnie od wszystkich moich projektów. Szybko i łatwo.
unfactorize <- function(df){
for(i in which(sapply(df, class) == "factor")) df[[i]] = as.character(df[[i]])
return(df)
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-10 22:25:09
Innym sposobem jest przekonwertowanie go za pomocą apply
bob2 <- apply(bob,2,as.character)
I lepszy (poprzedni należy do klasy 'matrix')
bob2 <- as.data.frame(as.matrix(bob),stringsAsFactors=F)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-17 17:58:36
Aktualizacja: oto przykład czegoś, co nie działa. Myślałem, że tak, ale myślę, że opcja stringsAsFactors działa tylko na ciągach znaków - pozostawia czynniki same.
Spróbuj tego:
bob2 <- data.frame(bob, stringsAsFactors = FALSE)
Ogólnie rzecz biorąc, gdy masz problemy z czynnikami, które powinny być postaciami, istnieje gdzieś ustawienie stringsAsFactors
, które Ci pomoże (w tym ustawienie globalne).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-17 17:07:27
Lub możesz spróbować transform
:
newbob <- transform(bob, phenotype = as.character(phenotype))
Pamiętaj, aby umieścić każdy czynnik, który chcesz przekonwertować na postać.
Albo możesz zrobić coś takiego i zabić wszystkie szkodniki jednym ciosem: {]}
newbob_char <- as.data.frame(lapply(bob[sapply(bob, is.factor)], as.character), stringsAsFactors = FALSE)
newbob_rest <- bob[!(sapply(bob, is.factor))]
newbob <- cbind(newbob_char, newbob_rest)
To nie dobry pomysł, żeby wepchnąć dane w taki kod, mógłbym zrobić część sapply
osobno( właściwie o wiele łatwiej to zrobić w ten sposób), ale rozumiesz o co chodzi... Nie sprawdziłem kodu, bo nie ma mnie w domu, więc mam nadzieję, że zadziała! =)
To podejście ma jednak minusy... następnie musisz przeorganizować kolumny, podczas gdy za pomocą transform
możesz robić, co chcesz, ale kosztem "pisania kodu w stylu pieszym" ...
Więc tam... =)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-17 17:49:17
Na początku ramki danych Dołącz stringsAsFactors = FALSE
, aby zignorować wszelkie nieporozumienia.
Jeśli chcesz użyć data.table
pakietu do operacji na danych.ramka wtedy problem nie występuje.
library(data.table)
dt = data.table(col1 = c("a","b","c"), col2 = 1:3)
sapply(dt, class)
# col1 col2
#"character" "integer"
Jeśli masz kolumny współczynników w zbiorze danych i chcesz je przekonwertować na znak, możesz wykonać następujące czynności.
library(data.table)
dt = data.table(col1 = factor(c("a","b","c")), col2 = 1:3)
sapply(dt, class)
# col1 col2
# "factor" "integer"
upd.cols = sapply(dt, is.factor)
dt[, names(dt)[upd.cols] := lapply(.SD, as.character), .SDcols = upd.cols]
sapply(dt, class)
# col1 col2
#"character" "integer"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-09 20:55:52
To działa dla mnie-w końcu wymyśliłem jeden liner
df <- as.data.frame(lapply(df,function (y) if(class(y)=="factor" ) as.character(y) else y),stringsAsFactors=F)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-24 16:00:22
Ta funkcja robi sztuczkę
df <- stacomirtools::killfactor(df)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-13 16:46:28
Może nowsza opcja?
library("tidyverse")
bob <- bob %>% group_by_if(is.factor, as.character)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-08-14 16:09:37
Powinieneś użyć convert
w hablar
co daje czytelną składnię zgodną ztidyverse
:
library(dplyr)
library(hablar)
df <- tibble(a = factor(c(1, 2, 3, 4)),
b = factor(c(5, 6, 7, 8)))
df %>% convert(chr(a:b))
Co daje:
a b
<chr> <chr>
1 1 5
2 2 6
3 3 7
4 4 8
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-06-10 21:25:45
Z dplyr
-pakiet załadowany
bob=bob%>%mutate_at("phenotype", as.character)
Jeśli chcesz tylko zmienić kolumnę phenotype
-konkretnie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-10 12:16:38
Nowa funkcja "across" została wprowadzona w dplyr w wersji 1.0.0 . Nowa funkcja zastąpi zmienne zakresowe (_if, _at, _all). Oto oficjalna Dokumentacja
library(dplyr)
bob <- bob %>%
mutate(across(where(is.factor), as.character))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-08-13 13:37:55
To działa przekształcając wszystkie na znak, a następnie numeryczne na numeryczne:
makenumcols<-function(df){
df<-as.data.frame(df)
df[] <- lapply(df, as.character)
cond <- apply(df, 2, function(x) {
x <- x[!is.na(x)]
all(suppressWarnings(!is.na(as.numeric(x))))
})
numeric_cols <- names(df)[cond]
df[,numeric_cols] <- sapply(df[,numeric_cols], as.numeric)
return(df)
}
Dostosowany z: Automatycznie pobieraj typy kolumn arkusza excel
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-08-27 19:23:06