多くの R データフレームの行値を交差させ、対応する値の平均を計算します。

okwaves2024-01-25  8

以下は例です。

df1 <- data.frame("names" = c('John','Peter','Jolie'), "value1" = c(21, 24, 26), "value2" = c(20, 23, 32))
df2 <- data.frame("names" = c('Sam','John','Jolie'), "value1" = c(35, 11, 10), "value2" = c(10, 28, 27))
df3 <- data.frame("names" = c('Louis','Jolie','John'), "value1" = c(42, 74, 26), "value2" = c(26, 53, 54))
df4 <- data.frame("names" = c('Ale','John','Jolie'), "value1" = c(61, 34, 76), "value2" = c(28, 63, 38))
df5 <- data.frame("names" = c('John','Jolie','peter'), "value1" = c(11, 84, 86), "value2" = c(50, 13, 68))

intersect_names <- Reduce(intersect, list(df1$names,df2$names,df3$names,df4$names,df5$names))

reduce コマンドと intersect コマンドを使用すると、すべての名前の交差部分を取得できます。ただし、データフレーム内の各名前の value1 と value2 の対応する平均が必要です。

期待される出力データフレーム:

 names   Value1 Value2
 John    20.6   43
 Jolie   54     32.6

例: 値 20.6 は、mean(c(21,11,26,34,11)) を取得することによって取得されました。



------------------------

データフレームのリストを作成し、intersect_names の行を抽出し、各名前の平均を取得します。

list_df <- mget(paste0('df', 1:5))
intersect_names <- Reduce(intersect, lapply(list_df, `[[`, 'names'))

aggregate(.~names, do.call(rbind, lapply(list_df, function(x) 
                           x[x$names %in% intersect_names, ])), mean)

tidyverse 関数を使用した場合も同様です:

library(dplyr)
library(purrr)

map_df(list_df, ~.x %>% filter(names %in% intersect_names)) %>%
  group_by(names) %>%
  summarise(across(.fns = mean))

#  names value1 value2
#  <chr>  <dbl>  <dbl>
#1 John    20.6   43  
#2 Jolie   54     32.6

2

この解決策は、私が尋ねた問題に対してうまく機能します。ただし、値の一部が負であり、絶対値を考慮して平均をとりたい場合は、コードを変更するにはどうすればよいですか?何か提案はありますか?

– ボットロギー

2020 年 9 月 5 日 6:08

1

匿名関数を集合的に使用できます。集約(.~names、do.call(rbind、lapply(list_df、function(x) x[x$names %in% intersect_names, ])), function(x) abs(mean(x)))

– ロナク・シャー

2020 年 9 月 5 日 6:21

総合生活情報サイト - OKWAVES
総合生活情報サイト - OKWAVES
生活総合情報サイトokwaves(オールアバウト)。その道のプロ(専門家)が、日常生活をより豊かに快適にするノウハウから業界の最新動向、読み物コラムまで、多彩なコンテンツを発信。