2014-01-30 2 views
1

У меня есть кадр данных с двумя столбцами: один - это строки, другой - целые числа.R: Совокупные символьные строки с c

> rnames = sapply(1:20, FUN=function(x) paste("item", x, sep=".")) 
> x <- sample(c(1:5), 20, replace = TRUE) 
> df <- data.frame(x, rnames) 
> df 
    x rnames 
1 5 item.1 
2 3 item.2 
3 5 item.3 
4 3 item.4 
5 1 item.5 
6 3 item.6 
7 4 item.7 
8 5 item.8 
9 4 item.9 
10 5 item.10 
11 5 item.11 
12 2 item.12 
13 2 item.13 
14 1 item.14 
15 3 item.15 
16 4 item.16 
17 5 item.17 
18 4 item.18 
19 1 item.19 
20 1 item.20 

Я пытаюсь агрегировать строки в списке или векторы строк (символов) с «с» или функции «список», но получать странные результаты:

> aggregate(rnames ~ x, df, c) 
    x    rnames 
1 1  16, 6, 11, 13 
2 2    4, 5 
3 3  12, 15, 17, 7 
4 4  18, 20, 8, 10 
5 5 1, 14, 19, 2, 3, 9 

Когда я используйте 'paste' вместо 'c', я вижу, что агрегат работает правильно, но результат не тот, который я ищу.

> aggregate(rnames ~ x, df, paste) 
    x           rnames 
1 1     item.5, item.14, item.19, item.20 
2 2         item.12, item.13 
3 3     item.2, item.4, item.6, item.15 
4 4     item.7, item.9, item.16, item.18 
5 5 item.1, item.3, item.8, item.10, item.11, item.17 

Что я ищу в том, что каждая агрегируются группа будет представлена ​​в виде вектора или зажженной (отсюда и использование с), в отличие от одной строки я получаю с «вставить». Что-то в строках следующего (что на самом деле не работает):

> aggregate(rnames ~ x, df, c) 
    x           rnames 
1 1     item.5, item.14, item.19, item.20 
2 2         item.12, item.13 
3 3     item.2, item.4, item.6, item.15 
4 4     item.7, item.9, item.16, item.18 
5 5 item.1, item.3, item.8, item.10, item.11, item.17 

Любая помощь будет принята с благодарностью.

ответ

5

Вы упали в обычной ловушке data.frame: Ваш символьный столбец не символьный столбец, это столбец фактора! Следовательно, числа вместо символов в ваш результат:

> rnames = sapply(1:20, FUN=function(x) paste("item", x, sep=".")) 
> x <- sample(c(1:5), 20, replace = TRUE) 
> df <- data.frame(x, rnames) 
> str(df) 
'data.frame': 20 obs. of 2 variables: 
$ x  : int 2 5 5 5 5 4 3 3 2 4 ... 
$ rnames: Factor w/ 20 levels "item.1","item.10",..: 1 12 14 15 16 17 18 19 20 2 ... 

Чтобы предотвратить преобразование к факторам, используйте аргумент stringAsFactors=FALSE в вызове к data.frame:

> df <- data.frame(x, rnames,stringsAsFactors=FALSE) 
> str(df) 
'data.frame': 20 obs. of 2 variables: 
$ x  : int 5 5 3 5 5 3 2 5 1 5 ... 
$ rnames: chr "item.1" "item.2" "item.3" "item.4" ... 
> aggregate(rnames ~ x, df, c) 
    x                    rnames 
1 1               item.9, item.13, item.17 
2 2                    item.7 
3 3                item.3, item.6, item.19 
4 4               item.12, item.15, item.16 
5 5 item.1, item.2, item.4, item.5, item.8, item.10, item.11, item.14, item.18, item.20 

Другое решение, чтобы избежать превращения в фактор функция I:

> df <- data.frame(x, I(rnames)) 
> str(df) 
'data.frame': 20 obs. of 2 variables: 
$ x  : int 3 5 4 5 4 5 3 3 1 1 ... 
$ rnames:Class 'AsIs' chr [1:20] "item.1" "item.2" "item.3" "item.4" ... 

Отрывок из ?I:

В функции data.frame. Защищая объект, заключая его в I() в , вызов data.frame запрещает преобразование векторов символов в факторов и отбрасывание имен и гарантирует, что матрицы вставлены как отдельные столбцы.Я также могу использовать для защиты объектов , которые должны быть добавлены в фрейм данных или преобразованы в кадр данных через as.data.frame.

Он достигает этого, добавляя класс «AsIs» к классам объекта . Класс «AsIs» имеет несколько своих собственных методов, в том числе для [, as.data.frame, печати и формата.

+0

Прохладный. Я что-то узнал! :-) – DataWookie

2

не уверен точно, что именно вы ищете ... так что, возможно, какой-то справочный результат был бы хорош, чтобы дать нам представление о том, на что мы нацелены?

Но, так как ваш последний бит кода, кажется, близка к тому, что вы после этого, может быть, решение, как следующее будет работать:

> library(plyr) 
> ddply(df, .(x), summarize, rnames = paste(rnames, collapse = "|")) 
    x           rnames 
1 1       item.9|item.11|item.20 
2 2     item.1|item.2|item.15|item.16 
3 3         item.7|item.8 
4 4   item.4|item.5|item.6|item.12|item.13 
5 5 item.3|item.10|item.14|item.17|item.18|item.19 

Вы можете изменять как отдельные элементы склеиваются путем изменения аргумент collapse для paste().

В качестве альтернативы, если вы хотите просто каждая из групп как VETOR то вы могли бы использовать это:

> df$rnames = as.character(df$rnames) 
> L = dlply(df, .(x), function(df) {df$rnames}) 
> L 
$`1` 
[1] "item.9" "item.11" "item.20" 

$`2` 
[1] "item.1" "item.2" "item.15" "item.16" 

$`3` 
[1] "item.7" "item.8" 

$`4` 
[1] "item.4" "item.5" "item.6" "item.12" "item.13" 

$`5` 
[1] "item.3" "item.10" "item.14" "item.17" "item.18" "item.19" 

attr(,"split_type") 
[1] "data.frame" 
attr(,"split_labels") 
    x 
1 1 
2 2 
3 3 
4 4 
5 5 

Это дает вам список векторов, который является то, что вы были после. И каждая группа может быть проиндексирована из полученного списка:

> L[[1]] 
[1] "item.9" "item.11" "item.20" 
+0

Я отредактировал вопрос. То, что я пытаюсь получить, состоит в том, что каждая агрегированная группа будет возвращена как вектор/список, а не одна строка, которую я получаю с помощью «paste». – Roy2012

Смежные вопросы