Получить значения символов вместо уровней факторов

Я застрял на, по-видимому, очень простой проблеме с факторными символьными переменными.

test = data.frame(uv=c("03834","06044","06054","03834","48557","48207","03834","06044","48557"))
test
uv=c()
for (i in 1:length(test$uv)){
  uv[i]=test[i,"uv"]
}
uv

И вот что я получаю:

> test = data.frame(uv=c("03834","06044","06054","03834","48557","48207","03834","06044","48557"))
> test
     uv
1 03834
2 06044
3 06054
4 03834
5 48557
6 48207
7 03834
8 06044
9 48557
> uv=c()
> for (i in 1:length(test$uv)){
+   uv[i]=test[i,"uv"]
+ }
> uv
[1] 1 2 3 1 5 4 1 2 5
> 

Мой вопрос: почему он сохраняет номера уровней вместо значений символов?

Я знаю, что если я поставлю:

     uv[i]=as.character(test[i,"uv"])

это работает, но в «реальной жизни» мои переменные могут быть числовыми, поэтому я не хочу заставлять их символизировать...

Как будто чего-то не хватает в моем понимании факторов!

Спасибо.


person Sam    schedule 09.11.2015    source источник
comment
Я думаю, что наиболее важной первоначальной причиной была экономия места, но есть и другие причины, чтобы сделать это таким образом, а именно тот факт, что строки символов часто на самом деле представляют какой-то перечисляемый тип. Но я думаю, что на это действительно должен ответить олдтаймер, который был рядом, когда принимались эти решения.   -  person Mike Wise    schedule 09.11.2015


Ответы (1)


Если вы относитесь к своей факторной переменной таким образом (итерация цикла для каждого элемента), то информация, которую она хранит, представляет собой позицию значения, а само значение хранится в «уровнях». Вы можете думать об этом как о таблице поиска, основанной на позициях.

Если вы сделаете это:

test = data.frame(uv=c("03834","06044","06054","03834","48557","48207","03834","06044","48557"))
test
uv= c()
for (i in 1:length(test$uv)){
  uv[i]=test[i,"uv"]
}

uv

# [1] 1 2 3 1 5 4 1 2 5

factor(uv, labels = levels(test$uv))

# [1] 03834 06044 06054 03834 48557 48207 03834 06044 48557
# Levels: 03834 06044 06054 48207 48557

Вы увидите, что можете использовать позиции и уровни из исходного набора данных для получения фактических значений. Это происходит потому, что вы можете работать с целыми числами быстрее, чем с символьными значениями. И единственный способ сделать это без потери информации — установить отношение 1 к 1 между фактическим значением символа и целым числом.

Если вы сделаете:

uv2 = test[,"uv"]
uv2

# [1] 03834 06044 06054 03834 48557 48207 03834 06044 48557
# Levels: 03834 06044 06054 48207 48557

Вы увидите, что uv2 содержит всю информацию, так как вы не перебирали каждый элемент, а использовали столбец факторов в целом.

Не уверен, что вы подразумеваете под «числовой переменной в реальной жизни». В этом случае у вас не возникнет никаких проблем, поскольку числовая переменная не является факторной или символьной переменной.

test = data.frame(uv=c(03834,06044,06054,03834))
test
uv= c()
for (i in 1:length(test$uv)){
  uv[i]=test[i,"uv"]
}

uv

# [1] 3834 6044 6054 3834

Но вы пропустите нули в начале числа.

Если вы предпочитаете работать с числовыми или символьными переменными, вы можете использовать опцию stringsAsFactors = F, которая гарантирует, что у вас не будет факторных переменных.

test = data.frame(uv=c("03834","06044","06054","03834","48557","48207","03834","06044","48557"),
                  stringsAsFactors = F)
test
uv= c()
for (i in 1:length(test$uv)){
  uv[i]=test[i,"uv"]
}

uv

# [1] "03834" "06044" "06054" "03834" "48557" "48207" "03834" "06044" "48557"

В этом случае ваш цикл без проблем будет обрабатывать числовые переменные как числовые, а символьные переменные как символы.

person AntoniosK    schedule 09.11.2015
comment
Большой ! Это хороший урок. Теперь я понимаю, почему и как. Большое спасибо за ответ! - person Sam; 09.11.2015