Объединить несколько кадров данных в r [duplicate]

protected Void doInBackground(Integer... params) 
{
    onProgessUpdate("Contacting server..Please wait..");
    ...
}

Urrrm, нет, это не сработает.

Попробуйте ...

publishProgress("Contacting server..Please wait..");

Вы должны «опубликовать» свой прогресс в doInBackground(..) в порядок для onProgressUpdate(...), который будет вызываться.

Также не вызывайте dialog.dismiss() в doInBackground(...) вместо этого в onPostExecute(...).

186
задан Community 23 May 2017 в 12:18
поделиться

7 ответов

Другой вопрос, заданный специально , как выполнить несколько левых объединений, используя dplyr в R . Вопрос был помечен как дубликат этого, поэтому я отвечу здесь, используя три примера данных:

library(dplyr)
x <- data_frame(i = c("a","b","c"), j = 1:3)
y <- data_frame(i = c("b","c","d"), k = 4:6)
z <- data_frame(i = c("c","d","a"), l = 7:9)

Обновление июня 2018 года: я разделил ответ в трех разделах, представляющих три разных способа выполнения слияние. Вероятно, вы захотите использовать путь purrr, если вы уже используете пакеты tidyverse. Для сравнения ниже вы найдете базовую версию R с использованием того же набора данных образца.

Присоедините их к reduce из пакета purrr

Пакет purrr предоставляет функцию reduce, которая имеет сжатый синтаксис:

library(tidyverse)
list(x, y, z) %>% reduce(left_join, by = "i")
#  A tibble: 3 x 4
#  i         j     k     l
#  <chr> <int> <int> <int>
# 1 a         1    NA     9
# 2 b         2     4    NA
# 3 c         3     5     7

Вы также можете выполнять другие объединения, такие как full_join или inner_join:

list(x, y, z) %>% reduce(full_join, by = "i")
# A tibble: 4 x 4
# i         j     k     l
# <chr> <int> <int> <int>
#   1 a         1    NA     9
# 2 b         2     4    NA
# 3 c         3     5     7
# 4 d        NA     6     8

list(x, y, z) %>% reduce(inner_join, by = "i")
# A tibble: 1 x 4
# i         j     k     l
# <chr> <int> <int> <int>
#   1 c         3     5     7

dplyr::left_join() с базой R Reduce()

list(x,y,z) %>%
    Reduce(function(dtf1,dtf2) left_join(dtf1,dtf2,by="i"), .)

#  i j  k  l
#1 a 1 NA  9
#2 b 2  4 NA
#3 c 3  5  7

База R merge() с базой R Reduce()

И для целей сравнения здесь представлена ​​базовая R-версия left join

 Reduce(function(dtf1, dtf2) merge(dtf1, dtf2, by = "i", all.x = TRUE),
        list(x,y,z))
#   i j  k  l
# 1 a 1 NA  9
# 2 b 2  4 NA
# 3 c 3  5  7
70
ответ дан Paul Rougieux 16 August 2018 в 10:30
поделиться
  • 1
    Вариант full_join работает отлично, и выглядит намного менее страшно, чем принятый ответ. Тем не менее, не большая разница в скорости. – bshor 21 December 2016 в 05:44
  • 2
    @Axeman прав, но вы можете избежать (видимо) возврата списка фреймов данных с помощью map_dfr() или map_dfc() – DaveRGP 30 June 2017 в 08:42

Более новое решение может быть доступно в пакете purrr. Для вашего точного вопроса вы можете использовать reduce() отметить малый r по сравнению с base::Reduce, но вы могли бы полностью устранить проблему, используя map_dfr() или map_dfc, которые могли бы предотвратить проблему, сделав карту и уменьшить шаг в одном.

-2
ответ дан DaveRGP 16 August 2018 в 10:30
поделиться

Я буду повторно использовать пример данных из @PaulRougieux

x <- data_frame(i = c("a","b","c"), j = 1:3)
y <- data_frame(i = c("b","c","d"), k = 4:6)
z <- data_frame(i = c("c","d","a"), l = 7:9)

Вот короткое и сладкое решение, использующее purrr и tidyr

library(tidyverse)

 list(x, y, z) %>% 
  map_df(gather, key=key, value=value, -i) %>% 
  spread(key, value)
1
ответ дан dmi3kno 16 August 2018 в 10:30
поделиться

Вы можете использовать рекурсию для этого. Я не проверял следующее, но он должен дать вам правильную идею:

MergeListOfDf = function( data , ... )
{
    if ( length( data ) == 2 ) 
    {
        return( merge( data[[ 1 ]] , data[[ 2 ]] , ... ) )
    }    
    return( merge( MergeListOfDf( data[ -1 ] , ... ) , data[[ 1 ]] , ... ) )
}
4
ответ дан SFun28 16 August 2018 в 10:30
поделиться

Вы можете сделать это, используя merge_all в пакете reshape. Вы можете передать параметры merge с помощью аргумента ...

reshape::merge_all(list_of_dataframes, ...)

. Это отличный ресурс для разных методов для объединения кадров данных .

44
ответ дан shadow 16 August 2018 в 10:30
поделиться
  • 1
    похоже, что я просто реплицировал merge_recurse =) хорошо знать, что эта функция уже существует. – SFun28 11 November 2011 в 17:29
  • 2
    да. всякий раз, когда у меня есть идея, я всегда проверяю, действительно ли @hadley уже сделал это, и большую часть времени у него :-) – Ramnath 11 November 2011 в 17:33
  • 3
    Я немного запутался; Должен ли я выполнять merge_all или merge_recurse? В любом случае, когда я пытаюсь добавить в свои дополнительные аргументы либо, я получаю ошибку «формальный аргумент» и все ». согласованный несколькими фактическими аргументами ". – bshor 11 November 2011 в 23:42
  • 4
    Я думаю, что я отказался от него. Уменьшить + слияние так же просто. – hadley 12 November 2011 в 06:45
  • 5
    @Ramnath, ссылка мертва, есть ли зеркало? – Eduardo 22 October 2014 в 08:29

Уменьшить делает это довольно легко:

merged.data.frame = Reduce(function(...) merge(..., all=T), list.of.data.frames)

Вот полный пример с использованием некоторых макетных данных:

set.seed(1)
list.of.data.frames = list(data.frame(x=1:10, a=1:10), data.frame(x=5:14, b=11:20), data.frame(x=sample(20, 10), y=runif(10)))
merged.data.frame = Reduce(function(...) merge(..., all=T), list.of.data.frames)
tail(merged.data.frame)
#    x  a  b         y
#12 12 NA 18        NA
#13 13 NA 19        NA
#14 14 NA 20 0.4976992
#15 15 NA NA 0.7176185
#16 16 NA NA 0.3841037
#17 19 NA NA 0.3800352

И вот пример использования этих данных для репликации my.list:

merged.data.frame = Reduce(function(...) merge(..., by=match.by, all=T), my.list)
merged.data.frame[, 1:12]

#  matchname party st district chamber senate1993 name.x v2.x v3.x v4.x senate1994 name.y
#1   ALGIERE   200 RI      026       S         NA   <NA>   NA   NA   NA         NA   <NA>
#2     ALVES   100 RI      019       S         NA   <NA>   NA   NA   NA         NA   <NA>
#3    BADEAU   100 RI      032       S         NA   <NA>   NA   NA   NA         NA   <NA>

Примечание: похоже, что это, возможно, ошибка в merge. Проблема в том, что нет никакой проверки того, что добавление суффиксов (для обработки перекрывающихся имен несоответствий) фактически делает их уникальными. В какой-то момент он использует [.data.frame, который делает make.unique имена, в результате чего rbind терпит неудачу.

# first merge will end up with 'name.x' & 'name.y'
merge(my.list[[1]], my.list[[2]], by=match.by, all=T)
# [1] matchname    party        st           district     chamber      senate1993   name.x      
# [8] votes.year.x senate1994   name.y       votes.year.y
#<0 rows> (or 0-length row.names)
# as there is no clash, we retain 'name.x' & 'name.y' and get 'name' again
merge(merge(my.list[[1]], my.list[[2]], by=match.by, all=T), my.list[[3]], by=match.by, all=T)
# [1] matchname    party        st           district     chamber      senate1993   name.x      
# [8] votes.year.x senate1994   name.y       votes.year.y senate1995   name         votes.year  
#<0 rows> (or 0-length row.names)
# the next merge will fail as 'name' will get renamed to a pre-existing field.

Самый простой способ исправить - это не оставить поле для переименования для полей дубликатов (которых здесь много) до merge. Например:

my.list2 = Map(function(x, i) setNames(x, ifelse(names(x) %in% match.by,
      names(x), sprintf('%s.%d', names(x), i))), my.list, seq_along(my.list))

merge / Reduce будет работать нормально.

202
ответ дан Thomas 16 August 2018 в 10:30
поделиться
  • 1
    Благодаря! Я видел это решение также по ссылке из Рамнатха. Выглядит достаточно просто. Но я получаю следующую ошибку: & quot; Ошибка в match.names (clabs, names (xi)): имена не соответствуют предыдущим именам & quot ;. Переменные, которые я сопоставляю, все присутствуют во всех фреймах данных в списке, поэтому я не понимаю, что говорит эта ошибка. – bshor 11 November 2011 в 23:49
  • 2
    Я протестировал это решение на R2.7.2, и я получил ту же ошибку match.names. Таким образом, есть еще одна фундаментальная проблема с этим решением и моими данными. Я использовал код: Reduce (функция (x, y) merge (x, y, all = T, by.x = match.by, by.y = match.by), my.list, accumulate = F) – bshor 14 November 2011 в 21:28
  • 3
    Странно, я добавил код, который я тестировал, с которым работает нормально. Наверное, есть какое-то переименование поля на основе аргументов merge args, которые вы используете? В объединенном результате все еще должны быть соответствующие ключи для объединения с последующим фреймом данных. – Charles 14 November 2011 в 22:12
  • 4
    Я подозреваю, что что-то происходит с пустыми кадрами данных. Я попробовал несколько примеров: empty <- data.frame(x=numeric(0),a=numeric(0); L3 <- c(empty,empty,list.of.data.frames,empty,empty,empty) и получил некоторые странные вещи, которые я еще не понял. – Ben Bolker 15 November 2011 в 00:10
  • 5
    @Charles Ты на что-то. Ваш код работает отлично для меня. И когда я приспосабливаю его к моему, он тоже отлично работает, за исключением того, что он выполняет слияние, игнорируя ключевые переменные, которые я хочу. Когда я пытаюсь добавить ключевые переменные, а не оставлять их, я получаю новую ошибку «Ошибка в is.null (x):« x »отсутствует». Кодовая строка «test.reduce & lt; - Уменьшить (функция (...) слить (by = match.by, all = T), my.list) & quot; где match.by - это вектор ключевых имен переменных, которые я хочу объединить. – bshor 15 November 2011 в 21:56
0
ответ дан Elias EstatisticsEU 29 October 2018 в 11:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: