কীভাবে দীর্ঘ থেকে প্রশস্ত ফর্ম্যাট থেকে ডেটা পুনরায় আকার দেওয়া যায়


262

নিম্নলিখিত ডেটা ফ্রেমটি পুনরায় সাজানোতে আমার সমস্যা হচ্ছে:

set.seed(45)
dat1 <- data.frame(
    name = rep(c("firstName", "secondName"), each=4),
    numbers = rep(1:4, 2),
    value = rnorm(8)
    )

dat1
       name  numbers      value
1  firstName       1  0.3407997
2  firstName       2 -0.7033403
3  firstName       3 -0.3795377
4  firstName       4 -0.7460474
5 secondName       1 -0.8981073
6 secondName       2 -0.3347941
7 secondName       3 -0.5013782
8 secondName       4 -0.1745357

আমি এটিকে পুনরায় আকার দিতে চাই যাতে প্রতিটি অনন্য "নাম" ভেরিয়েবল একটি নতুন নাম হয়, সেই সারিতে পর্যবেক্ষণ হিসাবে "মানগুলি" এবং নাম হিসাবে "সংখ্যা" থাকে। এর মতো বাছাই করুন:

     name          1          2          3         4
1  firstName  0.3407997 -0.7033403 -0.3795377 -0.7460474
5 secondName -0.8981073 -0.3347941 -0.5013782 -0.1745357

আমি দিকে তাকিয়ে করেছি meltএবং castএবং কয়েক অন্যান্য জিনিস, কিন্তু কোনোটাই কাজ বলে মনে হচ্ছে।



4
@ ফ্র্যাঙ্ক: এটি একটি আরও ভাল শিরোনাম। দীর্ঘ-ফর্ম এবং প্রশস্ত-ফর্মটি ব্যবহৃত স্ট্যান্ডার্ড পদ are এই শর্তাবলী অনুসন্ধান করে অন্য উত্তর খুঁজে পাওয়া যাবে না।
স্মিচ

আরও একটি প্রশ্ন: এটিকে কীভাবে বদলাতে হবে?
হ্যাপিলিয়াং

উত্তর:


255

reshapeফাংশন ব্যবহার :

reshape(dat1, idvar = "name", timevar = "numbers", direction = "wide")

13
+1 এবং আপনার বাহ্যিক প্যাকেজগুলির উপর নির্ভর করার দরকার নেই, যেহেতু এটি reshapeএসেছে stats। এটি দ্রুত! =)
এএল

@ ইন্দ্রা_প্যাটিল - আমি অন্য উত্তরগুলির মধ্যে একটিতে বর্ণিত হিসাবে পুনরায় আকার 2 প্যাকেজটি ব্যবহার করব। আপনি আপনার ব্যবহারের ক্ষেত্রে সুনির্দিষ্টভাবে একটি নতুন প্রশ্ন তৈরি করতে পারেন এবং এটি বের করতে না পারলে এটি পোস্ট করতে পারেন।
চেজ

5
reshapeএকটি ভয়ঙ্কর ফাংশন API এর এক অসামান্য উদাহরণ। এটি অকেজো খুব কাছে।
নোব্যাকিংডাউন

14
reshapeমতামত ও অনুরূপ যুক্তি নাম যে সব সহায়ক নয়। তবে, আমি খুঁজে পেয়েছি যে দীর্ঘ থেকে প্রশস্ত সময়ের জন্য আপনাকে data =আপনার ডেটা ফ্রেম সরবরাহ করতে হবে, idvar= আপনার গোষ্ঠীগুলি চিহ্নিত করে v.namesএমন ভেরিয়েবল , = ভেরিয়েবলগুলি প্রশস্ত বিন্যাসে একাধিক কলামে পরিণত হবে, timevar= মানগুলি যুক্ত হবে এমন ভেরিয়েবল থেকে v.namesব্যাপক বিন্যাসে, direction = wideএবং sep = "_"। যথেষ্ট পরিষ্কার? ;)
ব্রায়ান ডি

3
আমি বলব বেস বেস এখনও 2 থেকে 1 এর একটি ফ্যাক্টর দ্বারা ভোট ভিত্তিক জিতেছে
ভনজড

129

নতুন (2014 সালে) tidyrপ্যাকেজ এছাড়াও কেবল এই আছে, সঙ্গে gather()/ spread()জন্য শর্তাবলী হচ্ছে melt/cast

সম্পাদনা করুন: এখন, 2019 সালে, tidyr v 1.0 চালু করেছে এবং সেট করে ফেলেছে spreadএবং gatherএকটি অবমূল্যায়নের পথে, তার চেয়ে বেশি পছন্দ করে pivot_widerএবং pivot_longerযা আপনি এই উত্তরে বর্ণিত খুঁজে পেতে পারেন । আপনি যদি এর সংক্ষিপ্ত জীবনের একটি সংক্ষিপ্ত ঝলক চান তবে পড়ুন spread/gather

library(tidyr)
spread(dat1, key = numbers, value = value)

গিথুব থেকে ,

tidyrএকটি করে সাজিয়েছেন হয় reshape2পরিপাটি ডেটা ফ্রেমওয়ার্ক সংসর্গে ডিজাইন, এবং কাজের স্থানের জন্য হাত-ইন-হাত দিয়ে magrittrএবংdplyr তথ্য বিশ্লেষণ জন্য একটি কঠিন পাইপলাইন নির্মাণ করতে।

যেমনটি reshape2পুনর্নির্মাণের চেয়ে কম করেছে, tidyrতার চেয়েও কম করে reshape2। এটি বিশেষভাবে ডেটা জোয়ারের জন্য ডিজাইন করা হয়েছে reshape2, সাধারণ পুনর্নির্মাণের মতো নয় বা পুনরায় আকার দেওয়ার মতো সাধারণ সংগ্রহের জন্য। বিশেষত, অন্তর্নির্মিত পদ্ধতিগুলি কেবল ডেটা ফ্রেমের জন্য কাজ tidyrকরে এবং কোনও মার্জিন বা সমষ্টি সরবরাহ করে না।


5
কেবল আর কুকবুক পৃষ্ঠায় একটি লিঙ্ক যুক্ত করতে চেয়েছিলেন যা এই ফাংশনগুলির ব্যবহার tidyrএবং থেকে আলোচনা করে reshape2। এটি ভাল উদাহরণ এবং ব্যাখ্যা সরবরাহ করে।
জেক

71

আপনি এটি reshape()ফাংশনটি দিয়ে বা পুনরায় আকার প্যাকেজের melt()/ cast()ফাংশনগুলির সাহায্যে করতে পারেন । দ্বিতীয় বিকল্পের জন্য উদাহরণ কোড

library(reshape)
cast(dat1, name ~ numbers)

বা ব্যবহার reshape2

library(reshape2)
dcast(dat1, name ~ numbers)

2
এটি লক্ষণীয় যে আপনার যদি একটি পরিষ্কার "মান" কলাম না থাকে তবে কেবল ব্যবহার করা castবা দুর্দান্তভাবে dcastকাজ করবে না। চেষ্টা করুন dat <- data.frame(id=c(1,1,2,2),blah=c(8,4,7,6),index=c(1,2,1,2)); dcast(dat, id ~ index); cast(dat, id ~ index)এবং আপনি যা আশা করেন তা পাবেন না। আপনি value/value.var- cast(dat, id ~ index, value="blah")এবং dcast(dat, id ~ index, value.var="blah")উদাহরণস্বরূপ স্পষ্টভাবে নোট করা প্রয়োজন ।
থলেটমেল

44

আরেকটি বিকল্প যদি কর্মক্ষমতা একটি উদ্বেগের বিষয় ব্যবহার করা data.table'র সম্প্রসারণ reshape2গুলি গলে & dcast ফাংশন'

( তথ্যসূত্র: ডেটা টেবিলগুলি ব্যবহার করে দক্ষ পুনরায় আকার দেওয়া )

library(data.table)

setDT(dat1)
dcast(dat1, name ~ numbers, value.var = "value")

#          name          1          2         3         4
# 1:  firstName  0.1836433 -0.8356286 1.5952808 0.3295078
# 2: secondName -0.8204684  0.4874291 0.7383247 0.5757814

এবং, ডেটা.টিবল v1.9.6 হিসাবে আমরা একাধিক কলামে কাস্ট করতে পারি

## add an extra column
dat1[, value2 := value * 2]

## cast multiple value columns
dcast(dat1, name ~ numbers, value.var = c("value", "value2"))

#          name    value_1    value_2   value_3   value_4   value2_1   value2_2 value2_3  value2_4
# 1:  firstName  0.1836433 -0.8356286 1.5952808 0.3295078  0.3672866 -1.6712572 3.190562 0.6590155
# 2: secondName -0.8204684  0.4874291 0.7383247 0.5757814 -1.6409368  0.9748581 1.476649 1.1515627

5
data.tableপদ্ধতির সেরা! খুব দক্ষ ... আপনি name30-40 কলামের সংমিশ্রণে পার্থক্যটি দেখতে পাবেন !!
joel.wilson

আমি যদি সর্বোচ্চটা নিতে চাই?
টিফুং

@ টিফুং আপনি কি জিজ্ঞাসা করছেন তা আমি বুঝতে পারি না। একটি নতুন প্রশ্ন খোলার সেরা হতে পারে?
সিম্বলিক্সএইউ

ওপ এর প্রশ্নে 'সিম্বলিক্সএইউ' নাম এবং 'সংখ্যা' অনন্য সংমিশ্রণ। যদি তারা না থাকে এবং আমি পিভোটিংয়ের পরে প্রতিটি সংমিশ্রনের সর্বাধিক মান আনতে চাইতাম? খুব কটাক্ষ করে যদি প্রশ্ন হয় না। চিন্তার জন্য শুধু খাবার। ধন্যবাদ.
টিফুং

দুর্দান্ত উত্তর। ধন্যবাদ. একাধিক কলাম জন্য, আমি "ত্রুটি .subset2 মধ্যে (এক্স, আমি সঠিক = সঠিক)" আছে, এবং data.table dcast ব্যবহার অত্যাচার এটির সমাধান করতে পারে: দেখুন stackoverflow.com/a/44271092/190791
Timothée HENRY

26

আপনার উদাহরণস্বরূপ ডেটাফ্রেম ব্যবহার করে আমরা করতে পারলাম:

xtabs(value ~ name + numbers, data = dat1)

2
এটি একটি ভাল, তবে ফলাফলটি ফর্ম্যাট টেবিলের যা ডাটা.ফ্রেম বা ডেটা.টিটেবল হিসাবে পরিচালনা করা এতটা সহজ নাও হতে পারে, উভয়েরই প্রচুর প্যাকেজ রয়েছে
ক্লাউডসম্পিউটস

18

অন্যান্য দুটি বিকল্প:

বেস প্যাকেজ:

df <- unstack(dat1, form = value ~ numbers)
rownames(df) <- unique(dat1$name)
df

sqldf প্যাকেজ:

library(sqldf)
sqldf('SELECT name,
      MAX(CASE WHEN numbers = 1 THEN value ELSE NULL END) x1, 
      MAX(CASE WHEN numbers = 2 THEN value ELSE NULL END) x2,
      MAX(CASE WHEN numbers = 3 THEN value ELSE NULL END) x3,
      MAX(CASE WHEN numbers = 4 THEN value ELSE NULL END) x4
      FROM dat1
      GROUP BY name')

1
হার্ডকডিং নম্বরগুলির পরিবর্তে ক্যোয়ারীটি এভাবে সেট আপ করা যেতে পারে:ValCol <- unique(dat1$numbers);s <- sprintf("MAX(CASE WHEN numbers = %s THEN value ELSE NULL END) `%s`,", ValCol, ValCol);mquerym <- gsub('.{1}$','',paste(s, collapse = "\n"));mquery <- paste("SELECT name,", mquerym, "FROM dat1", "GROUP BY name", sep = "\n");sqldf(mquery)
এম--

13

বেস আর aggregateফাংশন ব্যবহার :

aggregate(value ~ name, dat1, I)

# name           value.1  value.2  value.3  value.4
#1 firstName      0.4145  -0.4747   0.0659   -0.5024
#2 secondName    -0.8259   0.1669  -0.8962    0.1681

11

এর ডেভেল সংস্করণ সহ tidyr ‘0.8.3.9000’, রয়েছে pivot_widerএবংpivot_longer 1 থেকে একাধিক কলামে পুনরায় আকার পরিবর্তন (লম্বা -> প্রশস্ত, প্রশস্ত -> দীর্ঘ, যথাক্রমে) করার যা এটি সাধারণীকরণযোগ্য। ওপির ডেটা ব্যবহার করা

-সিংল কলাম দীর্ঘ -> প্রশস্ত

library(dplyr)
library(tidyr)
dat1 %>% 
    pivot_wider(names_from = numbers, values_from = value)
# A tibble: 2 x 5
#  name          `1`    `2`    `3`    `4`
#  <fct>       <dbl>  <dbl>  <dbl>  <dbl>
#1 firstName   0.341 -0.703 -0.380 -0.746
#2 secondName -0.898 -0.335 -0.501 -0.175

-> কার্যকারিতা প্রদর্শনের জন্য অন্য কলাম তৈরি করেছে

dat1 %>% 
    mutate(value2 = value * 2) %>% 
    pivot_wider(names_from = numbers, values_from = c("value", "value2"))
# A tibble: 2 x 9
#  name       value_1 value_2 value_3 value_4 value2_1 value2_2 value2_3 value2_4
#  <fct>        <dbl>   <dbl>   <dbl>   <dbl>    <dbl>    <dbl>    <dbl>    <dbl>
#1 firstName    0.341  -0.703  -0.380  -0.746    0.682   -1.41    -0.759   -1.49 
#2 secondName  -0.898  -0.335  -0.501  -0.175   -1.80    -0.670   -1.00    -0.349

7

উইন-ভেক্টর (কল করা লোকেরা vtreat, seplyrএবং replyr) ডেকে আনে জিনিয়াস ডেটা বিজ্ঞানীদের কাছ থেকে খুব শক্তিশালী নতুন প্যাকেজcdata । এটি এই নথিতে এবং এই ব্লগ পোস্টে বর্ণিত "সমন্বিত ডেটা" নীতিগুলি প্রয়োগ করে । ধারণাটি হ'ল আপনি আপনার ডেটা কীভাবে সংগঠিত করেন তা নির্বিশেষে, "ডেটা সমন্বয়কারী" সিস্টেম ব্যবহার করে স্বতন্ত্র ডেটা পয়েন্টগুলি সনাক্ত করা উচিত। জন মাউন্টের সাম্প্রতিক ব্লগ পোস্টের একটি অংশ এখানে দেওয়া হয়েছে:

পুরো সিস্টেমটি দুটি আদিম বা অপারেটর সিডিটা :: মুভিভ্যালুউটোরোসডি () এবং সিডিটা :: মুভিভ্যালুওটোকলমসডিডি () এর উপর ভিত্তি করে। এই অপারেটরগুলির কাছে পাইভট, আন-পাইভট, ওয়ান-হট এনকোড, ট্রান্সপোজ, একাধিক সারি এবং কলামগুলি সরানো এবং অন্যান্য অনেকগুলি সাধারণ বিশেষ কেস হিসাবে রূপান্তরিত করে।

সিডিটা আদিমদের দিক থেকে অনেকগুলি বিভিন্ন অপারেশন লেখা সহজ। এই অপারেটরগুলি মেমরি বা বড় ডেটা স্কেলে ওয়ার্ক-ইন করতে পারে (ডাটাবেস এবং অ্যাপাচি স্পার্ক সহ; বড় ডেটার জন্য সিডিটা :: মুভিভ্যালুটিওরোজএন () এবং সিডিটা :: মুভিভ্যালুটিও কলামসন () রূপগুলি) ব্যবহার করে use রূপান্তরগুলি একটি নিয়ন্ত্রণ টেবিল দ্বারা নিয়ন্ত্রিত হয় যা নিজেই রূপান্তরটির (বা ছবি) একটি ডায়াগ্রাম।

আমরা প্রথমে কন্ট্রোল টেবিলটি তৈরি করব ( বিশদগুলির জন্য ব্লগ পোস্ট দেখুন) এবং তারপরে সারি থেকে কলামে ডেটা স্থানান্তর করব।

library(cdata)
# first build the control table
pivotControlTable <- buildPivotControlTableD(table = dat1, # reference to dataset
                        columnToTakeKeysFrom = 'numbers', # this will become column headers
                        columnToTakeValuesFrom = 'value', # this contains data
                        sep="_")                          # optional for making column names

# perform the move of data to columns
dat_wide <- moveValuesToColumnsD(tallTable =  dat1, # reference to dataset
                    keyColumns = c('name'),         # this(these) column(s) should stay untouched 
                    controlTable = pivotControlTable# control table above
                    ) 
dat_wide

#>         name  numbers_1  numbers_2  numbers_3  numbers_4
#> 1  firstName  0.3407997 -0.7033403 -0.3795377 -0.7460474
#> 2 secondName -0.8981073 -0.3347941 -0.5013782 -0.1745357

7

বেস reshapeফাংশন পুরোপুরি সূক্ষ্মভাবে কাজ করে:

df <- data.frame(
  year   = c(rep(2000, 12), rep(2001, 12)),
  month  = rep(1:12, 2),
  values = rnorm(24)
)
df_wide <- reshape(df, idvar="year", timevar="month", v.names="values", direction="wide", sep="_")
df_wide

কোথায়

  • idvar সারিগুলি পৃথক করে এমন ক্লাসগুলির কলাম
  • timevar প্রশস্ত কাস্ট করার ক্লাসগুলির কলাম
  • v.names সংখ্যার মানযুক্ত কলামটি
  • direction প্রশস্ত বা দীর্ঘ বিন্যাস নির্দিষ্ট করে
  • alচ্ছিক sepযুক্তি হ'ল timevarশ্রেণীর নাম এবং v.namesআউটপুটে ব্যবহৃত বিভাজক data.frame

যদি idvarউপস্থিত না থাকে তবে reshape()ফাংশনটি ব্যবহারের আগে একটি তৈরি করুন :

df$id   <- c(rep("year1", 12), rep("year2", 12))
df_wide <- reshape(df, idvar="id", timevar="month", v.names="values", direction="wide", sep="_")
df_wide

শুধু মনে রাখবেন যে idvarপ্রয়োজনীয়! timevarএবং v.namesঅংশ সহজ। এই ফাংশনটির আউটপুট অন্যদের কারও তুলনায় অনুমানযোগ্য, কারণ সবকিছু স্পষ্টভাবে সংজ্ঞায়িত করা হয়েছে।


1

অনেক সহজ উপায়!

devtools::install_github("yikeshu0611/onetree") #install onetree package

library(onetree)
widedata=reshape_toWide(data = dat1,id = "name",j = "numbers",value.var.prefix = "value")
widedata

        name     value1     value2     value3     value4
   firstName  0.3407997 -0.7033403 -0.3795377 -0.7460474
  secondName -0.8981073 -0.3347941 -0.5013782 -0.1745357

আপনি যদি চওড়া থেকে দীর্ঘ পর্যন্ত ফিরে যেতে চান তবে কেবল প্রশস্ত লম্বায় পরিবর্তন করুন এবং অবজেক্টে কোনও পরিবর্তন হবে না।

reshape_toLong(data = widedata,id = "name",j = "numbers",value.var.prefix = "value")

        name numbers      value
   firstName       1  0.3407997
  secondName       1 -0.8981073
   firstName       2 -0.7033403
  secondName       2 -0.3347941
   firstName       3 -0.3795377
  secondName       3 -0.5013782
   firstName       4 -0.7460474
  secondName       4 -0.1745357
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.