Как применить функцию к каждому элементу / ячейке data.frame?

Я хочу округлить до двух десятичных цифр значения, которые являются небольшими и целочисленных значений, которые являются большими. я хочу получить desired.df от df,

df <- data.frame(a = c(0.123, 123.456), b = c(321.321, 0.321))
desired.df <- data.frame(a = c(0.12, 123), b = c(321, 0.32))

df
#         a       b
# 1   0.123 321.321
# 2 123.456   0.321

desired.df
#        a      b
# 1   0.12    321
# 2    123   0.32

Как это сделать? я пытался apply и некоторые из его вариантов, очевидно, не в надлежащем порядке, а также вложенные * применять функции (например, *apply(df, function(x) *apply(y, function(y) ...))) но без везения...

Например, следующее не работает

round.my.way <- function(cell) {
if(cell < 2) return(round(cell, 2)) 
else return(round(cell, 0))
}

apply(df, 1:2, round.my.way)

Есть идеи?

РЕДАКТИРОВАТЬ Я действительно извиняюсь, я не подчеркнул, что размещены desired.df возможно, нужно больше форматировать каждую "ячейку" независимо во фрейме данных, но я этого не осознавал.

my.data.frame <- structure(list(mean = c(1.09586889552429, -0.488970742717109,                        
717.369670482251, 1430.22132153487), sd = c(14.6805055234266,                        
0.847924955832248, 3148.43113658712, 6224.1150344482), skew = c(15.4288196192469,    
-0.848099854154573, 15.6753519251057, 13.8872189273213), kurt = c(760.003399845995,  
3.42534233994167, 403.114382084221, 296.372235189872), min = c(0.0211657925274003, 
-6.63384131834086, 1.14376333333333, 1.51974013933333), X5.. = c(0.163422411626505, 
-1.94866860909688, 5.55001008333333, 8.48210945666667), X25.. = c(0.419624647887877, 
-0.940344070376478, 24.2286483333333, 40.2822858746667), median = c(0.712376790798036, 
-0.397878278400871, 79.5970091666667, 147.535862094), X75.. = c(1.11275078144806, 
0.0525922423468574, 300.39765875, 594.258755956833), X95.. = c(2.12897531610479, 
0.694437497721256, 2918.320405, 5614.78688014776), max = c(932.099715965617, 
3.36571976522158, 77776.31031, 151194.931773039), n = c(4046.23166666667, 
4046.23166666667, 4046.23166666667, 4046.23166666667)), .Names = c("mean", 
"sd", "skew", "kurt", "min", "X5..", "X25..", "median", "X75..", 
"X95..", "max", "n"), row.names = c(NA, 4L), class = "data.frame")

С одним из моих экспериментов я почти получаю то, что хочу:

apply(my.data.frame, c(1, 2), function(x) if(x < 2) round(x, 2) else round(x, 0))

производит:

     mean      sd  skew kurt   min  X5.. X25.. median  X75..   X95..    max
1    1.10   15.00 15.00  760  0.02  0.16  0.42   0.71   1.11    2.00    932
2   -0.49    0.85 -0.85    3 -6.63 -1.95 -0.94  -0.40   0.05    0.69      3
3  717.00 3148.00 16.00  403  1.14  6.00 24.00  80.00 300.00 2918.00  77776
4 1430.00 6224.00 14.00  296  1.52  8.00 40.00 148.00 594.00 5615.00 151195
     n
1 4046
2 4046
3 4046

который показывает последний n столбец как целые числа без десятичных знаков, но не остальные столбцы!

Но я бы хотел использовать форматирование, изменяющее ячейку:

     mean      sd  skew kurt   min  X5.. X25.. median  X75..   X95..    max
1    1.10      15    15  760  0.02  0.16  0.42   0.71   1.11    2.00    932
2   -0.49    0.85 -0.85    3 -6.63 -1.95 -0.94  -0.40   0.05    0.69      3
3     717    3148    16  403  1.14     6    24     80    300    2918  77776
4    1430    6224    14  296  1.52     8    40    148    594    5615 151195
     n
1 4046
2 4046
3 4046
4 4046

2 ответа

Быстрое решение с использованием data.table подход

library(data.table)

setDT(df)[, lapply(.SD, function(x) ifelse(x < 2, round(x, 2), round(x) ))]

#>        a      b
#> 1:   0.12 321.00
#> 2: 123.00   0.32

Ваша функция round.my.wayработает с apply, Используйте средний аргумент apply как для строк и столбцов c(1,2)

apply(df,c(1,2),round.my.way)
      a      b
[1,]   0.12 321.00
[2,] 123.00   0.32

Другое, которое может работать так же хорошо,

Предположение 1: Если вы cell значение less than 2 затем к round to 2 decimal places else 0 decimal places, Это основано на функции, которую вы написали выше.

df <- data.frame(a = c(0.123, 123.456), b = c(321.321, 0.321))
df <- as.matrix(df)
df1 <- ifelse(df < 2,round(df,2),round(df))
df1
#         a      b
# [1,]   0.12 321.00
# [2,] 123.00   0.32
df1 <- as.data.frame(df1)

Предположение 2: От вас ожидается выходной, я предполагаю, что все ваши diagonal elements (row number = column number) are rounded up to 2 decimal places и отдохнуть 0 decimal places, Если предположение верно, ниже здесь будет одно из решений:

  df <- data.frame(a = c(0.123, 123.456), b = c(321.321, 0.321))
  df <- as.matrix(df)
  df1 <- ifelse(row(df)==col(df),round(df,2),round(df))
  df1
  #      [,1]   [,2]
  # [1,]   0.12 321.00
  # [2,] 123.00   0.32
  df1 <- as.data.frame(df1)

Вы также можете использовать floor печатать до десятичных дробей, но выходные данные выводят количество цифр после десятичной дроби как 2 или 3, в зависимости от того, что больше в кадре данных, в этом случае мы имеем 0 а также 2 так что prints 2 decimal place for all elements, если ты round это к 3 десятичные знаки, это prints 321.000 за df[1,2] а также 123.000 за df[2,1]

 df <- data.frame(a = c(0.123, 123.456), b = c(321.321, 0.321))
 df <- as.matrix(df)
 df1 <- ifelse(row(df)==col(df),round(df,2),floor(df))
 df1
 #      [,1]   [,2]
 # [1,]   0.12 321.00
 # [2,] 123.00   0.32
 df1 <- as.data.frame(df1)

За 3 знака после запятой,

 df1 <- ifelse(row(df)==col(df),round(df,2),round(df))
 df1
 #      [,1]   [,2]
 # [1,]  0.123 321.000
 # [2,] 123.000   0.321
 df1 <- as.data.frame(df1)
Другие вопросы по тегам