ডেটা.টিবেলে কলামের ক্লাস রূপান্তর করুন


118

ডেটা.ট্যাবল ব্যবহার করে আমার সমস্যা আছে: আমি কীভাবে কলাম ক্লাস রূপান্তর করব? এখানে একটি সহজ উদাহরণ: ডেটা.ফ্রেম সহ আমার এটির রূপান্তর করতে কোনও সমস্যা নেই, ডেটা সহ। টেবিল আমি ঠিক জানি না কীভাবে:

df <- data.frame(ID=c(rep("A", 5), rep("B",5)), Quarter=c(1:5, 1:5), value=rnorm(10))
#One way: http://stackoverflow.com/questions/2851015/r-convert-data-frame-columns-from-factors-to-characters
df <- data.frame(lapply(df, as.character), stringsAsFactors=FALSE)
#Another way
df[, "value"] <- as.numeric(df[, "value"])

library(data.table)
dt <- data.table(ID=c(rep("A", 5), rep("B",5)), Quarter=c(1:5, 1:5), value=rnorm(10))
dt <- data.table(lapply(dt, as.character), stringsAsFactors=FALSE) 
#Error in rep("", ncol(xi)) : invalid 'times' argument
#Produces error, does data.table not have the option stringsAsFactors?
dt[, "ID", with=FALSE] <- as.character(dt[, "ID", with=FALSE]) 
#Produces error: Error in `[<-.data.table`(`*tmp*`, , "ID", with = FALSE, value = "c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2)") : 
#unused argument(s) (with = FALSE)

আমি কি এখানে স্পষ্ট কিছু মিস করি?

ম্যাথিউর পোস্টের কারণে আপডেট: আমি এর আগে একটি পুরানো সংস্করণ ব্যবহার করেছি, তবে 1.6.6 এ আপডেট করার পরেও (আমি যে সংস্করণটি এখন ব্যবহার করি) আমি এখনও একটি ত্রুটি পেয়েছি।

আপডেট 2: আসুন আমি বলি যে আমি শ্রেণীর "ফ্যাক্টর" এর প্রতিটি কলামকে একটি "চরিত্র" কলামে রূপান্তর করতে চাই, তবে কোন কলামটি কোন শ্রেণীর, তা আগাম জানি না। একটি ডেটা.ফ্রেম দিয়ে আমি নিম্নলিখিতগুলি করতে পারি:

classes <- as.character(sapply(df, class))
colClasses <- which(classes=="factor")
df[, colClasses] <- sapply(df[, colClasses], as.character)

আমি কি ডেটা টেবিলের সাথে অনুরূপ কিছু করতে পারি?

আপডেট 3:

সেশনআইএনফো () আর সংস্করণ 2.13.1 (2011-07-08) প্ল্যাটফর্ম: x86_64-pc-mingw32 / x64 (64-বিট)

locale:
[1] C

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] data.table_1.6.6

loaded via a namespace (and not attached):
[1] tools_2.13.1

data.tableপদ্ধতিগুলিতে "[" অপারেটর আর্গুমেন্টগুলি তার চেয়ে আলাদাdata.frame
আইআরটিএফএম

1
এর চেয়ে প্রকৃত ত্রুটিটি পেস্ট করুন #Produces error। যাইহোক +1। আমি কোন ত্রুটি পাই না, আপনার কোন সংস্করণ আছে? এই ক্ষেত্রে একটি সমস্যা রয়েছে যদিও, এটি আগে উত্থাপিত হয়েছিল, এফআর # 1224 এবং এফআর # 1493 সম্বোধনের পক্ষে উচ্চ অগ্রাধিকার। যদিও অ্যান্ডির উত্তরটি সবচেয়ে ভাল উপায়।
ম্যাট ডাউল

আমার প্রশ্নে এটি মিস করার জন্য @ ম্যাথহেডওল দুঃখিত, আমি আমার পোস্টটি আপডেট করেছি।
ক্রিস্টোফ_জে

1
@ ক্রিসটফ_জে ধন্যবাদ আপনি কি invalid times argumentত্রুটি সম্পর্কে নিশ্চিত ? আমার জন্য ভাল কাজ। আপনি যা সংস্করণ আছে?
ম্যাট ডাওল

আমি আমার পোস্টটি সেশনআইএনফো () দিয়ে আপডেট করেছি। যাইহোক, আমি আজ এটি আমার ওয়ার্ক মেশিনে পরীক্ষা করেছি। গতকাল, আমার হোম মেশিনে (উবুন্টু) একই ত্রুটি ঘটেছে। আমি আর আপডেট করব এবং দেখুন এখনও সমস্যা আছে কিনা।
ক্রিস্টোফ_জে

উত্তর:


104

একক কলামের জন্য:

dtnew <- dt[, Quarter:=as.character(Quarter)]
str(dtnew)

Classes ‘data.table’ and 'data.frame':  10 obs. of  3 variables:
 $ ID     : Factor w/ 2 levels "A","B": 1 1 1 1 1 2 2 2 2 2
 $ Quarter: chr  "1" "2" "3" "4" ...
 $ value  : num  -0.838 0.146 -1.059 -1.197 0.282 ...

ব্যবহার lapplyএবং as.character:

dtnew <- dt[, lapply(.SD, as.character), by=ID]
str(dtnew)

Classes ‘data.table’ and 'data.frame':  10 obs. of  3 variables:
 $ ID     : Factor w/ 2 levels "A","B": 1 1 1 1 1 2 2 2 2 2
 $ Quarter: chr  "1" "2" "3" "4" ...
 $ value  : chr  "1.487145280568" "-0.827845218358881" "0.028977182770002" "1.35392750102305" ...

2
@ ক্রিসটফ_জে দয়া করে আপনি যে গ্রুপিং কমান্ডের সাথে লড়াই করছেন (প্রকৃত সমস্যা) তা দেখান। ভাবেন আপনি হয়ত কিছু সাধারণ মিস করেছেন। কেন আপনি কলাম ক্লাস রূপান্তর করতে চেষ্টা করছেন?
ম্যাট ডাওল

1
@ ক্রিসটফ_জে আপনি যদি ডেটা.টেবিলগুলি পরিচালনা করার জন্য লড়াই করেন, তবে কেন কেবল সেগুলি অস্থায়ীভাবে ডেটা.ফ্রেমে রূপান্তর করবেন না, ডেটা সাফ করার পরে তাদের আবার ডেটা টেবিলগুলিতে রূপান্তর করবেন?
অ্যান্ড্রি

17
কলামগুলির একটি উপসেটের জন্য (তাদের সকলের পরিবর্তে) এটি করার অলঙ্কারাত্মক উপায় কী? আমি convcolsকলামগুলির একটি চরিত্র ভেক্টরকে সংজ্ঞায়িত করেছি । dt[,lapply(.SD,as.numeric),.SDcols=convcols]প্রায় তত্ক্ষণাত্ যখন dt[,convcols:=lapply(.SD,as.numeric),.SDcols=convcols]প্রায় আর জমাট বাঁধে, সুতরাং আমি অনুমান করছি যে আমি এটি ভুল করছি। ধন্যবাদ
ফ্রাঙ্ক

4
(নীচের Geneorama এর উত্তর @Frank দেখুন ম্যাট Dowle এর মন্তব্য stackoverflow.com/questions/7813578/... ); এটি আমার পক্ষে যথেষ্ট সহায়ক এবং মূর্তিমাফিক ছিল [উদ্ধৃতি শুরু করুন] আর একটি সহজ উপায় হ'ল set()উদাহরণ for (col in names_factors) set(dt, j=col, value=as.factor(dt[[col]]))[শেষ উদ্ধৃতি]
সোয়াহার্ট

4
আপনি কেন বাই আইডি বিকল্পটি ব্যবহার করবেন?
স্ক্যান

48

এটা চেষ্টা কর

DT <- data.table(X1 = c("a", "b"), X2 = c(1,2), X3 = c("hello", "you"))
changeCols <- colnames(DT)[which(as.vector(DT[,lapply(.SD, class)]) == "character")]

DT[,(changeCols):= lapply(.SD, as.factor), .SDcols = changeCols]

7
এখন আপনি Filterকলামগুলি সনাক্ত করতে ফাংশনটি ব্যবহার করতে পারেন , উদাহরণস্বরূপ: changeCols<- names(Filter(is.character, DT))
ডেভিড লিয়াল

1
আইএমও এটি আরও ভাল উত্তর, যে কারণে আমি নির্বাচিত উত্তর দিয়েছি।
জেমস হিরশর্ন

1
বা আরো সংক্ষেপে নিম্নোক্তভাবে: changeCols <- names(DT)[sapply(DT, is.character)]
সিন্ড্রি_বালদুর

8

এটিকে আরও সুস্পষ্ট করতে (উত্সাহিত হিসাবে) জেনোরামার উত্তরের ( https://stackoverflow.com/a/20808945/4241780 ) ম্যাট ডাউলের ​​মন্তব্য উত্থাপন করে আপনি ব্যবহার করতে পারেন for(...)set(...)


library(data.table)

DT = data.table(a = LETTERS[c(3L,1:3)], b = 4:7, c = letters[1:4])
DT1 <- copy(DT)
names_factors <- c("a", "c")

for(col in names_factors)
  set(DT, j = col, value = as.factor(DT[[col]]))

sapply(DT, class)
#>         a         b         c 
#>  "factor" "integer"  "factor"

2020-02-12 তারিখে ডিপেক্স প্যাকেজ দ্বারা নির্মিত (v0.3.0)

আরও তথ্যের জন্য https://stackoverflow.com/a/33000778/4241780 এ ম্যাট এর আরও একটি মন্তব্য দেখুন।

সম্পাদনা করুন।

যেমন এস্পেন এবং ইন হিসাবে উল্লিখিত হয়েছে help(set), j"কলামের নাম (গুলি) (অক্ষর) বা সংখ্যা (গুলি) (পূর্ণসংখ্যা) হতে হবে যখন কলাম (গুলি) ইতিমধ্যে বিদ্যমান আছে তখন মান নির্ধারিত হতে পারে"। তাই names_factors <- c(1L, 3L)কাজ করবে।


আপনি names_factorsএখানে যা যুক্ত করতে চান হতে পারে । আমি তা থেকে নেয়া হচ্ছে stackoverflow.com/a/20808945/1666063 তাই এটা names_factors = c('fac1', 'fac2')এই ক্ষেত্রে - যা কলাম names.But এটি উদাহরণস্বরূপ 1 কলাম সংখ্যা হতে পারে হয়; ncol (DT) যা সব কলাম রূপান্তর হবে
Espen Riskedal

@ এসপেন রিস্কেলাল ধন্যবাদ ভাল পয়েন্ট, পোস্টটি আরও সুস্পষ্ট করার জন্য আমি সম্পাদনা করেছি।
জেভিলিমন

2

এটি করার একটি খারাপ উপায়! এটি অন্যান্য অদ্ভুত সমস্যাগুলি সমাধান করার ক্ষেত্রে আমি কেবল এই উত্তরটি রেখে যাচ্ছি। এই আরও ভাল পদ্ধতিগুলি সম্ভবত নতুন ডেটা.টিবল সংস্করণগুলির আংশিক ফলাফল ... সুতরাং এই শক্তভাবে ডকুমেন্ট করার জন্য এটি মূল্যবান। প্লাস, সিনট্যাক্সের জন্য এটি একটি দুর্দান্ত বাক্য গঠন উদাহরণ eval substitute

library(data.table)
dt <- data.table(ID = c(rep("A", 5), rep("B",5)), 
                 fac1 = c(1:5, 1:5), 
                 fac2 = c(1:5, 1:5) * 2, 
                 val1 = rnorm(10),
                 val2 = rnorm(10))

names_factors = c('fac1', 'fac2')
names_values = c('val1', 'val2')

for (col in names_factors){
  e = substitute(X := as.factor(X), list(X = as.symbol(col)))
  dt[ , eval(e)]
}
for (col in names_values){
  e = substitute(X := as.numeric(X), list(X = as.symbol(col)))
  dt[ , eval(e)]
}

str(dt)

যা আপনাকে দেয়

Classes ‘data.table’ and 'data.frame':  10 obs. of  5 variables:
 $ ID  : chr  "A" "A" "A" "A" ...
 $ fac1: Factor w/ 5 levels "1","2","3","4",..: 1 2 3 4 5 1 2 3 4 5
 $ fac2: Factor w/ 5 levels "2","4","6","8",..: 1 2 3 4 5 1 2 3 4 5
 $ val1: num  0.0459 2.0113 0.5186 -0.8348 -0.2185 ...
 $ val2: num  -0.0688 0.6544 0.267 -0.1322 -0.4893 ...
 - attr(*, ".internal.selfref")=<externalptr> 

42
আর একটি সহজ উপায় হ'ল set()উদাহরণস্বরূপfor (col in names_factors) set(dt, j=col, value=as.factor(dt[[col]]))
ম্যাট ডাউল

1
আমি মনে করি আমার উত্তরটি সমস্ত সংস্করণের জন্য এটি এক লাইনে পূরণ করেছে। setযদিও আরও উপযুক্ত কিনা তা নিশ্চিত নয় ।
বেন রোলার্ট 5

1
এখানে আরও তথ্য for(...)set(...): stackoverflow.com/a/33000778/403310
ম্যাট ডাওল

1
@ সাকান ভাল প্রশ্ন। যদি আপনি এটি আগে জিজ্ঞাসা না করে পেতে পারেন তবে দয়া করে একটি নতুন প্রশ্ন জিজ্ঞাসা করুন। ভবিষ্যতে অন্যদের সহায়তা করে।
ম্যাট ডাউল

1
@ সাকান এটি আমি এটি করেছিলাম: github.com/geneorama/geneorama/blob/master/R/…
জেনোমার

0

আমি বেশ কয়েকটি পদ্ধতির চেষ্টা করেছি।

# BY {dplyr}
data.table(ID      = c(rep("A", 5), rep("B",5)), 
           Quarter = c(1:5, 1:5), 
           value   = rnorm(10)) -> df1
df1 %<>% dplyr::mutate(ID      = as.factor(ID),
                       Quarter = as.character(Quarter))
# check classes
dplyr::glimpse(df1)
# Observations: 10
# Variables: 3
# $ ID      (fctr) A, A, A, A, A, B, B, B, B, B
# $ Quarter (chr) "1", "2", "3", "4", "5", "1", "2", "3", "4", "5"
# $ value   (dbl) -0.07676732, 0.25376110, 2.47192852, 0.84929175, -0.13567312,  -0.94224435, 0.80213218, -0.89652819...

, বা অন্যথায়

# from list to data.table using data.table::setDT
list(ID      = as.factor(c(rep("A", 5), rep("B",5))), 
     Quarter = as.character(c(1:5, 1:5)), 
     value   = rnorm(10)) %>% setDT(list.df) -> df2
class(df2)
# [1] "data.table" "data.frame"

0

আমি এই জিনিসগুলি করার আরও সাধারণ এবং সুরক্ষিত উপায় সরবরাহ করি,

".." <- function (x) 
{
  stopifnot(inherits(x, "character"))
  stopifnot(length(x) == 1)
  get(x, parent.frame(4))
}


set_colclass <- function(x, class){
  stopifnot(all(class %in% c("integer", "numeric", "double","factor","character")))
  for(i in intersect(names(class), names(x))){
    f <- get(paste0("as.", class[i]))
    x[, (..("i")):=..("f")(get(..("i")))]
  }
  invisible(x)
}

ফাংশনটি ..নিশ্চিত করে যে আমরা ডেটা টেবিলের সুযোগ থেকে একটি পরিবর্তনশীল পেয়েছি; set_colclass আপনার কোলের ক্লাস সেট করবে। আপনি এটি এর মতো ব্যবহার করতে পারেন:

dt <- data.table(i=1:3,f=3:1)
set_colclass(dt, c(i="character"))
class(dt$i)

-1

যদি আপনার ডেটাতে কলামের নামের একটি তালিকা থাকে able টেবিল, আপনি কর শ্রেণিটি পরিবর্তন করতে চান:

convert_to_character <- c("Quarter", "value")

dt[, convert_to_character] <- dt[, lapply(.SD, as.character), .SDcols = convert_to_character]

এই উত্তরটি নীচের নীচে @ নেড়ার উত্তরের একটি খারাপ সংস্করণ। শুধু কি dt[, c(convert_to_character) := lapply(.SD, as.character), .SDcols=convert_to_character]বরং ধীর data.frame নিয়োগ ব্যবহার করার পরিবর্তে, রেফারেন্স দ্বারা দায়িত্ব অর্পণ করা।
altabq

-3

চেষ্টা করে দেখুন:

dt <- data.table(A = c(1:5), 
                 B= c(11:15))

x <- ncol(dt)

for(i in 1:x) 
{
     dt[[i]] <- as.character(dt[[i]])
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.