условно добавить строки к фреймам данных в списке фреймов данных - PullRequest
1 голос
/ 08 ноября 2019

У меня есть список фреймов данных, где у каждого фрейма данных есть 1 или 2 строки с именем «mis» или «syn» (образуют столбец с именем cat) и второй столбец с числовой частотой. Я хочу заполнить каждый фрейм данных так, чтобы, если строка «mis» отсутствует, добавляется строка mis с частотой = 0, а если строка «syn» отсутствует, добавляется строка syn с частотой 1:

###exmaple: 
#example list of dataframes:
df1<- as.data.frame(cbind(cat = c("mis", "syn"), freq= c(4, 2)))
df2<- as.data.frame(cbind(cat = "mis", freq= 1))
df3<- as.data.frame(cbind(cat = "syn", freq= 2))
df_list<- list(df1 = df1, df2 = df2, df3= df3)

выглядит так:

> df_list
$df1
cat freq
1 mis    4
2 syn    2

$df2
cat freq
1 mis    1

$df3
cat freq
1 syn    2

Ожидаемый результат:

> df_list
$df1
cat freq
mis    4
syn    2

$df2
cat freq
mis    1
syn    1

$df3
cat freq
syn    2
mis    0

что я пробовал: сначала я изменяю имена строк, чтобы по ним можно было искать

df_list_named<- lapply(df_list, function(x){ row.names(x)<-as.character(x$cat); x})

df_list_named
$df1
cat freq
mis mis    4
syn syn    2

$df2
cat freq
mis mis    1

$df3
cat freq
syn syn    2

Затем я пытался использовать цикл ifelse для добавления строк в те кадры данных, где это необходимо, но я не могу заставить его работать:

test<- lapply(df_list_named, function (x) ifelse(!row.names(df_list_named[[x]]) %in% "mis", rbind(df_list_named[[x]], c(cat = "mis", freq= 0)), 
                                                                                               ifelse(!row.names(df_list_named[[x]]) %in% "syn", rbind(df_list_named[[x]], c(cat = "syn", freq= 1))))

Ответы [ 2 ]

2 голосов
/ 08 ноября 2019

Вот один из способов сделать это с lapply

lapply(df_list, function(x) {
   if(all(c("mis", "syn") %in% x$cat))
      x
   else if("mis" %in% x$cat)
      rbind(x, data.frame(cat = "syn", freq = 1))
   else
      rbind(x, data.frame(cat = "mis", freq = 0))
})

#$df1
#  cat freq
#1 mis    4
#2 syn    2

#$df2
#  cat freq
#1 mis    1
#2 syn    1

#$df3
#  cat freq
#1 syn    2
#2 mis    0

data

df1<- data.frame(cat = c("mis", "syn"), freq= c(4, 2), stringsAsFactors = FALSE)
df2<- data.frame(cat = "mis", freq= 1,stringsAsFactors = FALSE)
df3<- data.frame(cat = "syn", freq= 2, stringsAsFactors = FALSE)
df_list<- list(df1 = df1, df2 = df2, df3= df3)
0 голосов
/ 08 ноября 2019

Вы можете использовать фрейм данных "base", merge со всеми фреймами данных в списке, используя Map. duplicated строки, созданные в уже заполненных фреймах данных, можно безопасно исключить с помощью !, поскольку они всегда помещаются в конец.

(base <- data.frame(cat=factor(c("syn", "mis")), freq=factor(1:0)))
#   cat freq
# 1 syn    1
# 2 mis    0

Map(function(x) {y <- (merge(x, base, all=TRUE));y[!duplicated(y$cat), ]}, df_list)
# $df1
#   cat freq
# 1 mis    4
# 3 syn    2
# 
# $df2
#   cat freq
# 1 mis    1
# 3 syn    1
# 
# $df3
#   cat freq
# 1 syn    2
# 3 mis    0

Данные

df_list <- list(df1 = structure(list(cat = structure(1:2, .Label = c("mis", 
"syn"), class = "factor"), freq = structure(2:1, .Label = c("2", 
"4"), class = "factor")), class = "data.frame", row.names = c(NA, 
-2L)), df2 = structure(list(cat = structure(c(cat = 1L), .Label = "mis", class = "factor"), 
    freq = structure(c(freq = 1L), .Label = "1", class = "factor")), class = "data.frame", row.names = c(NA, 
-1L)), df3 = structure(list(cat = structure(c(cat = 1L), .Label = "syn", class = "factor"), 
    freq = structure(c(freq = 1L), .Label = "2", class = "factor")), class = "data.frame", row.names = c(NA, 
-1L)))
...