Как удалить строку из файла data.frame без потери атрибутов - программирование
Подтвердить что ты не робот

Как удалить строку из файла data.frame без потери атрибутов

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

Что я хочу сделать, это удалить строку (№ 101) из data.frame. Он содержит данные теста и не должен появляться в моих анализах. Моя проблема: всякий раз, когда я подмножаюсь из data.frame, атрибуты (особенно комментарии) теряются.

str(x)
# x has comments for each variable
x <- x[1:100,]
str(x)
# now x has lost all comments

Хорошо документировано, что подмножество отбросит все атрибуты - пока это совершенно ясно. Руководство (например, http://stat.ethz.ch/R-manual/R-devel/library/base/html/Extract.data.frame.html) даже предлагает способ сохранения атрибутов:

## keeping special attributes: use a class with a
## "as.data.frame" and "[" method:


as.data.frame.avector <- as.data.frame.vector

`[.avector` <- function(x,i,...) {
  r <- NextMethod("[")
  mostattributes(r) <- attributes(x)
  r
}

d <- data.frame(i= 0:7, f= gl(2,4),
                u= structure(11:18, unit = "kg", class="avector"))
str(d[2:4, -1]) # 'u' keeps its "unit"

Я еще не дошел до R, чтобы понять, что именно происходит здесь. Однако простое выполнение этих строк (кроме последних трех) не изменяет поведение моего подмножества. Использование подмножества команд() с соответствующим вектором (100 раз TRUE + 1 FALSE) дает мне тот же результат. И просто сохранение атрибутов переменной и восстановление ее после подмножества тоже не работает.

# Does not work...
tmp <- attributes(x)
x <- x[1:100,]
attributes(x) <- tmp

Конечно, я мог бы написать все комментарии к вектору (var = > comment), подмножество и записать их с помощью цикла, но это не кажется обоснованным решением. И я совершенно уверен, что буду сталкиваться с наборами данных с другими соответствующими атрибутами в будущих анализах.

Итак, вот мои усилия в stackoverflow, Google и мозговой силе застряли. Я был бы очень признателен, если бы кто-нибудь мог помочь мне с намеком. Спасибо!

4b9b3361

Ответ 1

Если я правильно вас понимаю, у вас есть данные в файле data.frame, а в столбцах data.frame есть комментарии, связанные с ними. Возможно, что-то вроде следующего?

set.seed(1)

mydf<-data.frame(aa=rpois(100,4),bb=sample(LETTERS[1:5],
  100,replace=TRUE))

comment(mydf$aa)<-"Don't drop me!"
comment(mydf$bb)<-"Me either!"

Итак, это даст вам что-то вроде

> str(mydf)
'data.frame':   100 obs. of  2 variables:
 $ aa: atomic  3 3 4 7 2 7 7 5 5 1 ...
  ..- attr(*, "comment")= chr "Don't drop me!"
 $ bb: Factor w/ 5 levels "A","B","C","D",..: 4 2 2 5 4 2 1 3 5 3 ...
  ..- attr(*, "comment")= chr "Me either!"

И когда вы подмножите это, комментарии будут удалены:

> str(mydf[1:2,]) # comment dropped.
'data.frame':   2 obs. of  2 variables:
 $ aa: num  3 3
 $ bb: Factor w/ 5 levels "A","B","C","D",..: 4 2

Чтобы сохранить комментарии, определите функцию [.avector, как вы это делали выше (из документации), затем добавьте соответствующие атрибуты класса в каждый из столбцов вашего файла data.frame( EDIT: чтобы сохранить уровни факторов bb, добавьте "factor" в класс bb.):

mydf$aa<-structure(mydf$aa, class="avector")
mydf$bb<-structure(mydf$bb, class=c("avector","factor"))

Чтобы комментарии сохранялись:

> str(mydf[1:2,])
'data.frame':   2 obs. of  2 variables:
 $ aa:Class 'avector'  atomic [1:2] 3 3
  .. ..- attr(*, "comment")= chr "Don't drop me!"
 $ bb: Factor w/ 5 levels "A","B","C","D",..: 4 2
  ..- attr(*, "comment")= chr "Me either!"

EDIT:

Если в вашем файле data.frame есть много столбцов, у которых есть атрибуты, которые вы хотите сохранить, вы можете использовать lapply ( EDITED, чтобы включить исходный класс столбца):

mydf2 <- data.frame( lapply( mydf, function(x) {
  structure( x, class = c("avector", class(x) ) )
} ) )

Однако это уменьшает комментарии, связанные с самим файлом data.frame(например, comment(mydf)<-"I'm a data.frame"), поэтому, если у вас есть, назначьте их новому data.frame:

comment(mydf2)<-comment(mydf)

И тогда у вас есть

> str(mydf2[1:2,])
'data.frame':   2 obs. of  2 variables:
 $ aa:Classes 'avector', 'numeric'  atomic [1:2] 3 3
  .. ..- attr(*, "comment")= chr "Don't drop me!"
 $ bb: Factor w/ 5 levels "A","B","C","D",..: 4 2
  ..- attr(*, "comment")= chr "Me either!"
 - attr(*, "comment")= chr "I'm a data.frame"

Ответ 2

Для тех, кто ищет решение "все в одном", основанное на объяснении BenBarnes: Вот оно.

(дайте "вверх" на почту от BenBarnes, если это работает для вас)

# Define the avector-subselection method (from the manual)
as.data.frame.avector <- as.data.frame.vector
`[.avector` <- function(x,i,...) {
  r <- NextMethod("[")
  mostattributes(r) <- attributes(x)
  r
}

# Assign each column in the data.frame the (additional) class avector
# Note that this will "lose" the data.frame attributes, therefore write to a copy
df2 <- data.frame(
  lapply(df, function(x) {
    structure( x, class = c("avector", class(x) ) )
  } )
)

# Finally copy the attribute for the original data.frame if necessary
mostattributes(df2) <- attributes(df)

# Now subselects work without losing attributes :)
df2 <- df2[1:100,]
str(df2)

Хорошая вещь: при присоединении класса ко всему элементу data.frame один раз, subselects никогда больше не беспокоят атрибуты.

Хорошо - иногда я ошеломлен тем, насколько сложно выполнять самые простые операции в R. Но я, конечно же, не узнал о функции "classes", если я только что отметил и удалил случай в SPSS;)

Ответ 3

Это решается пакетом sticky. (Полное раскрытие: я автор пакета.) Примените sticky() к вашим векторам, и атрибуты сохраняются с помощью операций подмножества. Например:

> df <- data.frame( 
+   sticky   = sticky( structure(1:5, comment="sticky attribute") ),
+   nonstick = structure( letters[1:5], comment="non-sticky attribute" )
+ )
> 
> comment(df[1:3, "nonstick"])
NULL
> comment(df[1:3, "sticky"])
[1] "sticky attribute"

Это работает для любого атрибута, а не только comment.

Подробнее см. пакет sticky: