2012-03-12 2 views
0

Я пытаюсь создать набор данных из исходного фрейма данных (в коде R или Excel VBA), и я пытаюсь создать другой столбец. Вот ситуация высокого уровня:R/VBA - Сортировка данных

dfr <- data.frame(
    grp = rep(c("X", "Y"), each = 4), 
    id = c("A", "B", "C", "D", "E", "A", "B", "F"), 
    value = c(3, 7, 2, 4, 8, 9, 11, 2) 
) 

Из второй колонны, В является «лидером» из обеих групп «X» и «Y», как это имеет наибольшее число. Таким образом, мне нужно соединить все наблюдения с другими наблюдениями в соответствующих группах (X, Y) с этими лидерами. Например, пример вывода ниже того, что мне нужно:

X B A 3 
X B C 2 
X B D 4 
Y B E 8 
Y B A 9 
Y B F 2 

Номер на дальнем столбце соответствующий номер точки данных найденного ранее.

Итак, мне нужна помощь в разбивке данных между X и Y (для бесчисленных строковых групп, которые существуют), а затем, сортируя ее так, как мне нужно, и имея этот столбец в R-коде или VBA для excel (данные находятся в формате CSV)

** Отказ от ответственности: если это не очевидно, мое использование R очень ограничено - я использовал его в течение 4 месяцев на курсе Applied Econometrics, и теперь я нуждаюсь в он снова (9months позже), поэтому, пожалуйста, прости меня, если я, кажется, как новичок ... Я могу запустить регрессии просто отлично, хотя :)

* UPDATE После кода Генри, т его там, где я сейчас.

data <- read.csv(file = "sort.csv", h=T) 
attach(data) 
sorted <- data[order(data$membernumber, -data$dailycirc),] 
top <- function(df){ return(df[1,])} 
moded <- unsplit(lapply(split(sorted, sorted$membernumber), top), unique(sorted$membernumber))[1:2] 
names(moded) <- c("membernumber", "cnty") 
merged <- merge(moded, data, by="membernumber") 
merged[merged$cnty != merged$cnty, ] 
summary(merged) 

Это фактически дало мне некоторый результат. Но я не вижу такого рода, просто сводную статистику таких вещей, как средний/макс. Как я фактически экспортирую это в CSV или таблицу, чтобы я мог смотреть на нее как на таблицу?

Благодарим вас за помощь.

+0

G в ваших данных отсутствует. – Henry

+0

Прочтите краткие сведения о проблемах с split-apply-comb. http://4dpiecharts.com/2011/12/16/a-quick-primer-on-split-apply-combine-problems/ –

+0

@ Генри, спасибо вам за G, я решил сделать его «B» последним, минута, чтобы подчеркнуть, что категории X & Y могут иметь много перекрывающихся областей (ссылка A, B..etc) @Roman, к сожалению, я все еще пытаюсь написать псевдокод и обернуть вокруг него свой разум. Я еще не написал код. – Dman

ответ

0

Поскольку только R люди, похоже, будить до Я чувствовал себя обязанным опубликовать пример в VBA. Я предполагаю, что вы открыли свой CSV в Excel с информацией в первых трех столбцах, без заголовка (данные начинаются в строке 1). Вы скопируете данные в новую таблицу на вкладке «Лист1». Вы вставляете код ниже в новый модуль и запускаете его, и он выводит результат в столбцы с 5 по 8 того же листа. Для ввода 10 000 строк он работает менее 0,1 секунды на моей машине.

Option Explicit 

Public Sub doIt() 

    Dim data As Variant 
    Dim result As Variant 
    Dim i As Long 
    Dim j As Long 
    Dim dict1 As Variant 
    Dim dict2 As Variant 

    Set dict1 = CreateObject("Scripting.Dictionary") 
    Set dict2 = CreateObject("Scripting.Dictionary") 
    data = Sheets("Sheet1").UsedRange 

    For i = LBound(data, 1) To UBound(data, 1) 
     If dict1.exists(data(i, 1)) Then 
      If dict2(data(i, 1)) < data(i, 3) Then 
       dict1(data(i, 1)) = data(i, 2) 
       dict2(data(i, 1)) = data(i, 3) 
      End If 
     Else 
      dict1(data(i, 1)) = data(i, 2) 
      dict2(data(i, 1)) = data(i, 3) 
     End If 
    Next i 

    ReDim result(LBound(data, 1) To UBound(data, 1) - dict1.Count, 1 To 4) As Variant 

    j = 1 
    For i = LBound(data, 1) To UBound(data, 1) 
     If data(i, 2) <> dict1(data(i, 1)) Then 
      result(j, 1) = data(i, 1) 
      result(j, 2) = dict1(data(i, 1)) 
      result(j, 3) = data(i, 2) 
      result(j, 4) = data(i, 3) 
      j = j + 1 
     End If 
    Next i 

    With Sheets("Sheet1") 
     .Cells(1, 5).Resize(UBound(result, 1), UBound(result, 2)) = result 
    End With 

End Sub 
+0

Это для меня гораздо более читаемый код - я действительно понимаю VBA! Один вопрос: у меня на самом деле есть 6 столбцов, а 10 733 строки - первая строка заголовков. Я должен предоставить аналогичный результат, но также все столбцы должны быть частью вывода. – Dman

+0

@Dman Вы просто хотите скопировать все, что находится в следующих 3 столбцах после 4-го столбца в вашем примере вывода? – assylias

+0

Я посвятил еще один код для вашего кода! – Dman

0

Это, вероятно, не лучшее решение, и кто-то, скорее всего, даст вам лучшее решение, используя пакет reshape, но, похоже, он работает для вашего примера и нескольких других, которые я пробовал.

df = data.frame(c(sample(c(LETTERS), 10000,replace=T)), 
       sample(LETTERS[1:5],10000,replace=T), 
       runif(10000)) 
names(df) = c("id","grp", "value") 
i = levels(df$id)[1] 

groupings = lapply(levels(df$i), function(i){ 
            d = subset(df,df$id==i) 
            l = length(d$value[d$id==i]) 
            m = max(d$value) 
            leader= d$grp[d$value==m] 
            piece = data.frame(id = rep(i,l), 
                 grp= rep(as.character(leader),l), 
                 grp2 = d$grp, 
                 value = d$value) 

            }) 

df.final = do.call(rbind,groupings) 
+0

Спасибо за это, но я пытаюсь воспроизвести этот анализ более чем на 10 000 наблюдений. У меня нет навыка, чтобы взять ваш код на этот уровень! – Dman

+0

Вы проверили это на 10 000 наблюдений? потому что он работает менее чем за 5 секунд. Незначительная проблема с длинами, я отредактирую, чтобы исправить. По-прежнему предлагаю вам пойти с одним из ответов выше. –

1

Используя plyr пакет, попробуйте

ddply(dfr, .(grp), transform, id.max = id[which.max(value)]) 

Много отдельных вопросов здесь, но, похоже, что вам нужно несколько советов, чтобы начать работать с R.

data <- read.csv(file = "sort.csv", h=T) 

Не используйте T для TRUE, в один прекрасный день вы объявите переменную nam ed T и создать сложную для поиска ошибку. У меня также будет соблазн wrtie header вместо h, так как будет более очевидно, что делает код, когда вы вернетесь к нему еще через 9 месяцев.


attach(data) 

Neve использовать attach. Это еще один прекрасный источник для поиска ошибок. Вместо этого используйте with.


sorted <- data[order(data$membernumber, -data$dailycirc),] 

...как этот

sorted <- data[with(data, order(membernumber, -dailycirc)), ] 

top <- function(df){ return(df[1,])} 

head функция делает это уже.


moded <- unsplit(lapply(split(sorted, sorted$membernumber), top), unique(sorted$membernumber))[1:2] 

Это где tapply или ddply приходит. Что-то вроде

moded <- with(sorted, tapply(cnty, membernumber, head, n = 1)) 

(Проверьте эту строку. Так как я не могу воспроизвести ваш пример, трудно точно сказать, что это должно быть .)


merged[merged$cnty != merged$cnty, ] 

Поскольку условие всегда равно FALSE, это должно возвращать пустой фрейм данных. Вы уверены, что имеете в виду это?


Использование write.csv или writeLines для написания заметок в файл.

+0

Это отличное начало, я читаю документы и ссылки. я получил следующее сообщение об ошибке: Ошибка в разборе (текст = х): : 1: 5: неожиданный символ 1: ЗВЕЗДА ^ ли вы быть в состоянии помочь мне понять это немного больше? Я чувствую, что ты поставил меня на большой путь, и я просто немного неопытен с R, чтобы нести себя полностью. – Dman

+0

'parse' берет строку символов и пытается превратить ее в выражение R.'' STAR^"' недействителен R, поэтому вы получили сообщение об ошибке. Я не уверен, как это относится к исходному вопросу. Если у вас есть отдельные проблемы с 'parse', задайте их в другом вопросе. –

1

Следующий

sorted <- dfr[order(dfr$grp, -dfr$value), ] 
top <- function(df){ return(df[1,]) } 
moded <- unsplit(lapply(split(sorted, sorted$grp), top), unique(sorted$grp))[1:2] 
names(moded) <- c("grp", "leader") 
merged <- merge(moded, dfr, by="grp") 
merged[merged$leader != merged$id, ] 

производит

grp leader id value 
1 X  B A  3 
3 X  B C  2 
4 X  B D  4 
5 Y  B E  8 
6 Y  B A  9 
8 Y  B F  2 

и

> summary(merged) 
grp leader id  value  
X:4 A:0 A:2 Min. : 2.00 
Y:4 B:8 B:2 1st Qu.: 2.75 
     C:0 C:1 Median : 5.50 
     D:0 D:1 Mean : 5.75 
     E:0 E:1 3rd Qu.: 8.25 
     F:0 F:1 Max. :11.00 
+0

Дорогой Генри, не могли бы вы помочь мне сделать этот код переведённым на 10 000+ наблюдений? Кроме того, у меня нет R-фона, чтобы видеть ваш код и вынимать структуру высокого уровня, в которой я нуждаюсь, чтобы разместить свои собственные имена переменных + заголовки. – Dman

+0

@Dman: Первая строка сортируется по 'grp', а затем в обратном порядке по' value'; вторая и третья строки берут первые два столбца верхнего 'значения' для каждого' grp'; четвертая строка переименовывает те столбцы (которые были 'grp' и' id') на 'grp' и' leader'; пятая строка объединяется с данными, поэтому каждый 'grp' имеет свой« лидер »; Шестая строка удаляет те случаи, когда «лидер» и «id» одинаковы. – Henry

+0

@ Генри: Я думаю, что у меня это есть, теперь, как мне создать таблицу с этим? Я попробовал пакет WriteXLS и получил это: WriteXLS (слияние, «WriteXLS.xls», perl = perl) Ошибка в get (x, envir = envir): object 'integer (0)' not found – Dman

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