2012-01-30 2 views
16

У меня есть dataframe, и я хочу округлить все числа (готовые к экспорту). Это должно быть просто, но у меня возникают проблемы, потому что некоторые биты данных являются не числовыми числами. Например, я хочу, чтобы округлить цифры до ближайшего целого числа в примере ниже:Как объединить data.frame в R, который содержит некоторые переменные символов?

ID = c("a","b","c","d","e") 
Value1 = c("3.4","6.4","8.7","1.1","0.1") 
Value2 = c("8.2","1.7","6.4","1.9","10.3") 
df<-data.frame(ID,Value1,Value2) 

Может кто-нибудь помочь мне? Я могу объединить отдельные столбцы (например, round(df$Value1, 2)), но я хочу округлить целую таблицу, которая содержит несколько столбцов, которые не являются числовыми.

+1

Округление имеет смысл для «чисел», а не символов. Вам придется преобразовать 'Value1' и' Value2' как 'numeric', например. 'round (as.numeric (Value1), 0)' выполнит задание, но вы не указали, как должно выполняться округление (поиск одного из 'trunc',' ceiling' или 'floor'). – chl

ответ

22

Сначала убедитесь, что число столбцов являются числовыми:

ID = c("a","b","c","d","e") 
Value1 = as.numeric(c("3.4","6.4","8.7","1.1","0.1")) 
Value2 = as.numeric(c("8.2","1.7","6.4","1.9","10.3")) 
df<-data.frame(ID,Value1,Value2, stringsAsFactors = FALSE) 

Тогда, круглые только числовые столбцы:

df[,-1] <-round(df[,-1],0) #the "-1" excludes column 1 
df 

    ID Value1 Value2 
1 a  3  8 
2 b  6  2 
3 c  9  6 
4 d  1  2 
5 e  0  10 
+0

Это прекрасно - именно то, что я хотел. Спасибо огромное! –

0

Почему бы вам просто не использовать ID в качестве имени строки?

... и вывезти «'s из value1 и value2 данных

Попробуйте вместо этого:

ID = c("a","b","c","d","e") 
Value1 = c(3.4,6.4,8.7,1.1,0.1) 
Value2 = c(8.2,1.7,6.4,1.9,10.3) 

df<-data.frame(ID,Value1,Value2,row.names=TRUE) 

> df 
    Value1 Value2 
a 3.4 8.2 
b 6.4 1.7 
c 8.7 6.4 
d 1.1 1.9 
e 0.1 10.3 

> str(df) 
'data.frame': 5 obs. of 2 variables: 
$ Value1: num 3.4 6.4 8.7 1.1 0.1 
$ Value2: num 8.2 1.7 6.4 1.9 10.3 

Я не уверен, что вы хотите сделать с раунда, но у вас есть некоторые опции в R:

?ceiling() 
?floor() 
?trunc() 
+2

В случае, если вы знаете, какие столбцы вы хотите округлить и преобразовать, вы также можете выполнить 'df [, c ('Value1', 'Value2')] <- round (as.numeric (df [, c ('Value1 ',' Value2 ')])) '(это может быть желательно, если имеется много текстовых столбцов, но только несколько, которые могут быть сделаны числовыми). –

+6

Кроме того, если вы хотите искать только числовые столбцы и круги, вы можете использовать 'df [, sapply (df, is.numeric)] <-round (df [, sapply (df, is.numeric)], 0)' –

+0

Спасибо Tyler! Это было именно то, что я искал - вы сэкономили много времени! – TiF

27

Признавая, что это старый вопрос, и один ответ будет принят, я хотел бы предложить другое решение, так как возникает вопрос, как топ-рейтинг результата на Google.

Более общее решение создать отдельную функцию, которая ищет всех числовых переменных и округляет их до указанного количества цифр:

round_df <- function(df, digits) { 
    nums <- vapply(df, is.numeric, FUN.VALUE = logical(1)) 

    df[,nums] <- round(df[,nums], digits = digits) 

    (df) 
} 

После того, как определено, вы можете использовать его следующим образом:

> round_df(df, digits=3) 
+1

Это потрясающе, спасибо! – spacedSparking

4

Другие ответы не совсем отвечают на вопрос ОП именно потому, что они предполагают, что данные примера отличаются от того, что предоставил ОП.

Если мы читаем вопрос буквально, и мы хотим получить общее решение, в котором будут найдены столбцы с цифрами в них (любого векторного типа), преобразовать их в числовые и затем выполнить другую числовую операцию, такую ​​как округление.Мы можем использовать purrr:dmap и сделать это так:

Вот данные, как это предусмотрено ОП, где все перевалы являются факторами (раздражающий по умолчанию, но мы можем иметь дело с этим):

ID = c("a","b","c","d","e") 
Value1 = c("3.4","6.4","8.7","1.1","0.1") 
Value2 = c("8.2","1.7","6.4","1.9","10.3") 
df<-data.frame(ID,Value1,Value2) 

str(df) 
'data.frame': 5 obs. of 3 variables: 
$ ID : Factor w/ 5 levels "a","b","c","d",..: 1 2 3 4 5 
$ Value1: Factor w/ 5 levels "0.1","1.1","3.4",..: 3 4 5 2 1 
$ Value2: Factor w/ 5 levels "1.7","1.9","10.3",..: 5 1 4 2 3 

Мы» будет искать перевалы с цифрами в них, и сделать dataframe индексов для обозначения цифр:

library(dplyr) 
library(purrr) 

df_logical <- 
df %>% 
    dmap(function(i) grepl("[0-9]", i)) 

df_logical 
    ID Value1 Value2 
1 FALSE TRUE TRUE 
2 FALSE TRUE TRUE 
3 FALSE TRUE TRUE 
4 FALSE TRUE TRUE 
5 FALSE TRUE TRUE 

str(df_logical) 
'data.frame': 5 obs. of 3 variables: 
$ ID : logi FALSE FALSE FALSE FALSE FALSE 
$ Value1: logi TRUE TRUE TRUE TRUE TRUE 
$ Value2: logi TRUE TRUE TRUE TRUE TRUE 

Тогда мы можем использовать эти показатели, чтобы выбрать подмножество перевалов в оригинальной dataframe и конвертировать их в цифровой, и делать другие вещи (в данном случае округление):

df_numerics <- 
map(1:ncol(df), function(i) ifelse(df_logical[,i], 
             as.numeric(as.character(df[,i])), 
             df[,i])) %>% 
    dmap(round, 0) %>% 
    setNames(names(df)) 

И мы получили желаемый результат:

df_numerics 
    ID Value1 Value2 
1 1  3  8 
2 2  6  2 
3 3  9  6 
4 4  1  2 
5 5  0  10 

str(df_numerics) 
'data.frame': 5 obs. of 3 variables: 
$ ID : num 1 2 3 4 5 
$ Value1: num 3 6 9 1 0 
$ Value2: num 8 2 6 2 10 

Это может быть полезно в случае dataframe с большим количеством столбцов, и где у нас есть много COLS символьного типа/фактора полный цифр, которые мы хотим как числовые, но это слишком утомительно делать вручную.

12

Я знаю, что это поздний ответ, но у меня также была эта проблема. После выполнения некоторых поисков я нашел это самое элегантное решение:

data.frame(lapply(x, function(y) if(is.numeric(y)) round(y, 2) else y)) 

Решение родом из: Жан В. Адамс Statistician US Geological Survey Научный центр Great Lakes 223 East Steinfest Дорога Антиго, WI 54409 USA

http://r.789695.n4.nabble.com/round-a-data-frame-containing-character-variables-td3732415.html

+0

Это стандартное решение. –

7

Вот один-вкладыш, который мне нравится, используя: (это будет применять round функция только столбцы типа класса, указанный в classes аргументе)

df2 <- rapply(object = df, f = round, classes = "numeric", how = "replace", digits = 0) 
1

Ответов выше точек из за пару камней преткновения в первоначальном вопросе, что делает его более сложным, чем просто округление нескольких столбцов, в первую очередь:

  1. число было введено как символы, и
  2. data.frame() по умолчанию преобразует символьный-номер факторы

Ответ Бен подробно описывает, как обращаться с этими проблемами, и применяется purrr::dmap(). Пакет purrr был изменен и функция dmap устарела (в пользу map_df()).
Существует также более новая функция, modify_if(), которая может решить проблему округления нескольких числовых столбцов, и поэтому я хотел бы обновить этот ответ.


Я ввожу данные в виде цифр, добавив еще несколько цифр, округлить, чтобы сделать пример более широко применимой:

df <- data.frame(ID = c("a","b","c","d","e"), 
       Value1 =c(3.4532897,6.41325,8.71235,1.115,0.115), 
       Value2 = c(8.2125,1.71235,6.4135,1.915,10.3235)) 

Использование purrr::modify_if() функции:

purrr::modify_if(df, ~is.numeric(.), ~round(., 0)) 

    ID Value1 Value2 
1 a  3  8 
2 b  6  2 
3 c  9  6 
4 d  1  2 
5 e  0  10 

просто перейдите на round(digits= 0) в соответствующие десятичные пробелы

modify_if(df, ~is.numeric(.), ~round(., 2)) 
    ID Value1 Value2 
1 a 3.45 8.21 
2 b 6.41 1.71 
3 c 8.71 6.41 
4 d 1.12 1.92 
5 e 0.12 10.32 

см http://purrr.tidyverse.org/ дополнительную документацию по синтаксису

Это также может быть сделано в два этапа с использованием базы R применять функции, создав индекс для столбцов (numVars), а затем стандартной индексации изменять только те столбцы:

numVars <- sapply(df, is.numeric) 
    ID Value1 Value2 
FALSE TRUE TRUE 

df[, numVars] <- lapply(df[, numVars], round, 0) 
df 
    ID Value1 Value2 
1 a  3  8 
2 b  6  2 
3 c  9  6 
4 d  1  2 
5 e  0  10 
+0

Обратите внимание, что 'numVars <- apply (df, 2, is.numeric)' fail, потому что он принуждает файл данных к матрице (преобразует все столбцы в один и тот же тип-символ). 'sapply()' не делает этого. –

+0

изменить, если, похоже, не существует в текущем пакете purrr. Я получаю ошибки, говорящие, что не найдено modify_if после загрузки и загрузки пакета purrr – Mark

+0

@Mark hmmm ... Я только что проверил и находится в текущей версии CRAN (purrr 0.2.3). Я немного отредактировал команду, так что это 'purrr :: modify_if', так что вам не нужно загружать пакет. посмотрите, поможет ли это. –

9

Я думаю, опрятный способ сделать это сейчас с помощью dplyr

library(dplyr) 
df %>% 
mutate_if(is.numeric, round) 

Это круглый цифрового Колума ns в вашей информационной камере

+0

Блестящий!'Библиотека (dplyr); df%>% mutate_if (is.numeric, round, digits = 3) ' – rudeboybert

0

Обратите внимание, что некоторые решения (например, Alvis's) не заботятся о именах строк, а это означает, что они потерялись.

Try: df <- data.frame(v1 = seq(1.11, 1.20, 0.01), v2 = letters[1:10])

row.names(df)=df$v2

теперь попробуйте data.frame(lapply(df, function(y) if(is.numeric(y)) round(y, 2) else y)) как предложено Алвис. имена строк больше не существуют.

Предложение Ахмеда хранит имена строк, поскольку оно работает с заменами.

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