Разбить большой фрейм данных на список фреймов данных на основе общего значения в столбце
у меня есть фрейм данных с 10 столбцами, собирающий действия "пользователей", где один из столбцов содержит идентификатор (не уникальный, идентифицирующий пользователя)(столбец 10). длина фрейма данных составляет около 750000 строк. Я пытаюсь извлечь отдельные фреймы данных (таким образом, получая список или вектор фреймов данных), разделенные столбцом, содержащим идентификатор "пользователь", чтобы изолировать действия одного актора.
ID | Data1 | Data2 | ... | UserID
1 | aaa | bbb | ... | u_001
2 | aab | bb2 | ... | u_001
3 | aac | bb3 | ... | u_001
4 | aad | bb4 | ... | u_002
в результате
list(
ID | Data1 | Data2 | ... | UserID
1 | aaa | bbb | ... | u_001
2 | aab | bb2 | ... | u_001
3 | aac | bb3 | ... | u_001
,
4 | aad | bb4 | ... | u_002
...)
следующие работы очень ну для меня на небольшой выборке (1000 строк):
paths = by(smallsampleMat, smallsampleMat[,"userID"], function(x) x)
а затем доступ к элементу я хочу по путям[1] например.
при применении к исходному большому фрейму данных или даже матричному представлению это душит мою машину ( 4GB RAM, MacOSX 10.6, R 2.15) и никогда не завершается (я знаю, что существует более новая версия R, но я считаю, что это не главная проблема).
кажется, что раскол является более производительным, и после долгого времени завершается, но я не знаю (подчиненное знание R) как собрать результирующий список векторов в вектор матриц.
path = split(smallsampleMat, smallsampleMat[,10])
я рассматривал также использование big.matrix
и т. д., Но без особого успеха, что бы ускорить процесс.
2 ответа:
вы можете так же легко получить доступ к каждому элементу в списке, используя, например,
path[[1]]
. Вы не можете поместить набор матриц в атомарный вектор и получить доступ к каждому элементу. Матрица-это атомарный вектор с атрибутами измерения. Я бы использовал структуру списка, возвращеннуюsplit
, это то, для чего он был разработан. Каждый элемент списка может содержать данные разных типов и размеров, поэтому он очень универсален, и вы можете использовать*apply
функции для дальнейшей работы с каждым элементом в списке. Образец под.# For reproducibile data set.seed(1) # Make some data userid <- rep(1:2,times=4) data1 <- replicate(8 , paste( sample(letters , 3 ) , collapse = "" ) ) data2 <- sample(10,8) df <- data.frame( userid , data1 , data2 ) # Split on userid out <- split( df , f = df$userid ) #$`1` # userid data1 data2 #1 1 gjn 3 #3 1 yqp 1 #5 1 rjs 6 #7 1 jtw 5 #$`2` # userid data1 data2 #2 2 xfv 4 #4 2 bfe 10 #6 2 mrx 2 #8 2 fqd 9
доступ к каждому элементу с помощью
[[
оператор как это:out[[1]] # userid data1 data2 #1 1 gjn 3 #3 1 yqp 1 #5 1 rjs 6 #7 1 jtw 5
или использовать
*apply
функция для выполнения дальнейших операций над каждым элементом списка. Например, взять среднее значениеdata2
столбец вы можете использовать sapply следующим образом:sapply( out , function(x) mean( x$data2 ) ) # 1 2 #3.75 6.25
наткнулся на этот ответ, и я действительно хотел обе группы (данные, содержащие этого одного пользователя и данные, содержащие все, кроме этого одного пользователя). Не обязательно для специфики этого поста, но я подумал, что добавлю, если кто-то гуглил ту же проблему, что и я.
Вот как это выглядит:df <- data.frame( ran_data1=rnorm(125), ran_data2=rnorm(125), g=rep(factor(LETTERS[1:5]), 25) ) test_x = split(df,df$g)[['A']] test_y = split(df,df$g!='A')[['TRUE']]
head(test_x) x y g 1 1.1362198 1.2969541 A 6 0.5510307 -0.2512449 A 11 0.0321679 0.2358821 A 16 0.4734277 -1.2889081 A 21 -1.2686151 0.2524744 A > head(test_y) x y g 2 -2.23477293 1.1514810 B 3 -0.46958938 -1.7434205 C 4 0.07365603 0.1111419 D 5 -1.08758355 0.4727281 E 7 0.28448637 -1.5124336 B 8 1.24117504 0.4928257 C