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


164

আমার data.frameপ্রশস্ত টেবিল থেকে লম্বা টেবিলে রূপান্তর করতে আমার কিছুটা সমস্যা আছে । এই মুহুর্তে এটির মতো দেখাচ্ছে:

Code Country        1950    1951    1952    1953    1954
AFG  Afghanistan    20,249  21,352  22,532  23,557  24,555
ALB  Albania        8,097   8,986   10,058  11,123  12,246

এখন আমি এটিকে data.frameদীর্ঘায়িত করতে চাই data.frame। এটার মতো কিছু:

Code Country        Year    Value
AFG  Afghanistan    1950    20,249
AFG  Afghanistan    1951    21,352
AFG  Afghanistan    1952    22,532
AFG  Afghanistan    1953    23,557
AFG  Afghanistan    1954    24,555
ALB  Albania        1950    8,097
ALB  Albania        1951    8,986
ALB  Albania        1952    10,058
ALB  Albania        1953    11,123
ALB  Albania        1954    12,246

আমি দিকে তাকিয়ে আছে এবং ইতিমধ্যে ব্যবহার করার চেষ্টা melt()এবং reshape()কিছু লোক যেমন ফাংশন অনুরূপ প্রশ্ন পরামর্শ করা হয়েছে। তবে, এখন পর্যন্ত আমি কেবল অগোছালো ফলাফল পেয়েছি।

যদি এটি সম্ভব হয় তবে আমি reshape()এটিটি ফাংশনটি দিয়ে করতে চাই কারণ এটি পরিচালনা করতে কিছুটা সুন্দর লাগছে ।


2
সমস্যাটি কিনা তা জানুন না, তবে পুনরায় আকার প্যাকেজটিতে ফাংশনগুলি দ্রবীভূত হয়ে castালাই (এবং পুনঃনির্মাণ করুন
এডুয়ার্ডো লিওনি

1
এবং পুনঃ আকার প্যাকেজটি পুনঃ আকার 2 দ্বারা ছাড়িয়ে গেছে।
আইআরটিএফএম

5
এবং এখন পুনর্নির্মাণ 2 পরিশ্রম দ্বারা পরাস্ত করা হয়েছে
drhagen

উত্তর:


93

reshape()অভ্যস্ত হতে কিছুটা সময় নেয় ঠিক যেমন melt/ cast। আপনার ডেটা ফ্রেমটি ডাকা হয়েছে ধরেই ধরে নিয়ে পুনরায় আকারের সাথে একটি সমাধান এখানে দেওয়া হয়েছে d:

reshape(d, 
        direction = "long",
        varying = list(names(d)[3:7]),
        v.names = "Value",
        idvar = c("Code", "Country"),
        timevar = "Year",
        times = 1950:1954)

153

তিনটি বিকল্প সমাধান:

1) সাথে :

আপনি প্যাকেজ meltহিসাবে একই ফাংশন ব্যবহার করতে পারেন reshape2(যা একটি বর্ধিত এবং উন্নত বাস্তবায়ন)। meltথেকে data.tableআরও বেশি পরামিতি রয়েছে যা থেকে meltফাংশন reshape2। আপনি উদাহরণস্বরূপ চলক-কলামের নামও নির্দিষ্ট করতে পারেন:

library(data.table)
long <- melt(setDT(wide), id.vars = c("Code","Country"), variable.name = "year")

যা দেয়:

> long
    Code     Country year  value
 1:  AFG Afghanistan 1950 20,249
 2:  ALB     Albania 1950  8,097
 3:  AFG Afghanistan 1951 21,352
 4:  ALB     Albania 1951  8,986
 5:  AFG Afghanistan 1952 22,532
 6:  ALB     Albania 1952 10,058
 7:  AFG Afghanistan 1953 23,557
 8:  ALB     Albania 1953 11,123
 9:  AFG Afghanistan 1954 24,555
10:  ALB     Albania 1954 12,246

কিছু বিকল্প স্বরলিপি:

melt(setDT(wide), id.vars = 1:2, variable.name = "year")
melt(setDT(wide), measure.vars = 3:7, variable.name = "year")
melt(setDT(wide), measure.vars = as.character(1950:1954), variable.name = "year")

2) সাথে :

library(tidyr)
long <- wide %>% gather(year, value, -c(Code, Country))

কিছু বিকল্প স্বরলিপি:

wide %>% gather(year, value, -Code, -Country)
wide %>% gather(year, value, -1:-2)
wide %>% gather(year, value, -(1:2))
wide %>% gather(year, value, -1, -2)
wide %>% gather(year, value, 3:7)
wide %>% gather(year, value, `1950`:`1954`)

3) সাথে :

library(reshape2)
long <- melt(wide, id.vars = c("Code", "Country"))

কিছু বিকল্প স্বীকৃতি যা একই ফলাফল দেয়:

# you can also define the id-variables by column number
melt(wide, id.vars = 1:2)

# as an alternative you can also specify the measure-variables
# all other variables will then be used as id-variables
melt(wide, measure.vars = 3:7)
melt(wide, measure.vars = as.character(1950:1954))

মন্তব্য:

  • অবসরপ্রাপ্ত এটি CRAN এ রাখার জন্য প্রয়োজনীয় পরিবর্তনগুলি করা হবে। ( উত্স )
  • আপনি যদি NAমানগুলি বাদ দিতে চান তবে na.rm = TRUEআপনি ফাংশনগুলির meltপাশাপাশি যোগ করতে পারেন gather

ডেটাতে আর একটি সমস্যা হ'ল মানগুলি আর দ্বারা অক্ষর-মান হিসাবে পড়বে ( ,সংখ্যাগুলির ফলাফল হিসাবে )। আপনি এটি দিয়ে gsubএবং এটি মেরামত করতে পারেন as.numeric:

long$value <- as.numeric(gsub(",", "", long$value))

বা সরাসরি সাথে data.tableবা dplyr:

# data.table
long <- melt(setDT(wide),
             id.vars = c("Code","Country"),
             variable.name = "year")[, value := as.numeric(gsub(",", "", value))]

# tidyr and dplyr
long <- wide %>% gather(year, value, -c(Code,Country)) %>% 
  mutate(value = as.numeric(gsub(",", "", value)))

ডেটা:

wide <- read.table(text="Code Country        1950    1951    1952    1953    1954
AFG  Afghanistan    20,249  21,352  22,532  23,557  24,555
ALB  Albania        8,097   8,986   10,058  11,123  12,246", header=TRUE, check.names=FALSE)

দুর্দান্ত উত্তর, আরও একটি ছোট্ট অনুস্মারক: আপনার ডেটা ফ্রেম ব্যতীত idআর কোনও ভেরিয়েবল রাখবেন না, এই ক্ষেত্রে আপনি কী করতে চান তা বলতে পারেন নি। timemelt
জেসন গোল

1
@ জেসনগোয়াল আপনি কি সে সম্পর্কে বিস্তারিত বলতে পারবেন? আমি আপনাকে মন্তব্য হিসাবে ব্যাখ্যা করছি, এটি কোনও সমস্যা হওয়া উচিত নয়। শুধু id.varsএবং উভয়ই নির্দিষ্ট করুন measure.vars
জাপ

, তবে এটি আমার পক্ষে ভাল, জানেন না id.varsএবং measure.varsপ্রথম বিকল্পে এটি নির্দিষ্ট করা যেতে পারে, গণ্ডগোলের জন্য দুঃখিত, এটি আমার দোষ।
জেসন গোল

এই পোস্টটি নেক্রো করার জন্য দুঃখিত - 3 জন কেন কাজ করে কেউ আমাকে ব্যাখ্যা করতে পারে ? আমি এটি পরীক্ষা করেছি এবং এটি কাজ করে, তবে dplyr যখন এটি দেখছে তখন কী করছে তা আমি বুঝতে পারি না -c(var1, var2)...

1
@ রিপ্যুটেবলমিসনোমার যখন পরিশ্রমী দেখেন -c(var1, var2)তখন ডেটা প্রশস্ত থেকে দীর্ঘ বিন্যাসে রূপান্তর করার সময় এই পরিবর্তনগুলি বাদ দেয়।
জাপ

35

পুনরায় আকার প্যাকেজ ব্যবহার :

#data
x <- read.table(textConnection(
"Code Country        1950    1951    1952    1953    1954
AFG  Afghanistan    20,249  21,352  22,532  23,557  24,555
ALB  Albania        8,097   8,986   10,058  11,123  12,246"), header=TRUE)

library(reshape)

x2 <- melt(x, id = c("Code", "Country"), variable_name = "Year")
x2[,"Year"] <- as.numeric(gsub("X", "" , x2[,"Year"]))

18

সাথে tidyr_1.0.0, অন্য একটি বিকল্পpivot_longer

library(tidyr)
pivot_longer(df1, -c(Code, Country), values_to = "Value", names_to = "Year")
# A tibble: 10 x 4
#   Code  Country     Year  Value 
#   <fct> <fct>       <chr> <fct> 
# 1 AFG   Afghanistan 1950  20,249
# 2 AFG   Afghanistan 1951  21,352
# 3 AFG   Afghanistan 1952  22,532
# 4 AFG   Afghanistan 1953  23,557
# 5 AFG   Afghanistan 1954  24,555
# 6 ALB   Albania     1950  8,097 
# 7 ALB   Albania     1951  8,986 
# 8 ALB   Albania     1952  10,058
# 9 ALB   Albania     1953  11,123
#10 ALB   Albania     1954  12,246

উপাত্ত

df1 <- structure(list(Code = structure(1:2, .Label = c("AFG", "ALB"), class = "factor"), 
    Country = structure(1:2, .Label = c("Afghanistan", "Albania"
    ), class = "factor"), `1950` = structure(1:2, .Label = c("20,249", 
    "8,097"), class = "factor"), `1951` = structure(1:2, .Label = c("21,352", 
    "8,986"), class = "factor"), `1952` = structure(2:1, .Label = c("10,058", 
    "22,532"), class = "factor"), `1953` = structure(2:1, .Label = c("11,123", 
    "23,557"), class = "factor"), `1954` = structure(2:1, .Label = c("12,246", 
    "24,555"), class = "factor")), class = "data.frame", row.names = c(NA, 
-2L))

1
এটির জন্য আরও বেশি পরিমাণের প্রয়োজন। পরিশ্রমী ব্লগের মতে gatherঅবসর নেওয়া হচ্ছে এবং এটি সম্পাদনেরpivot_longer এখন সঠিক উপায় is
ইভান রোজিকা

16

যেহেতু এই উত্তরটি ট্যাগ করা হয়েছে , আমি অনুভব করলাম এটা বেস আর থেকে অন্য বিকল্প ভাগ করার জন্য উপযোগী হতে হবে: stack

উল্লেখ্য, যে stackনা কাজ নেই factorগুলি - এটি শুধুমাত্র কাজ করে is.vectorহয় TRUE, এবং নথিপত্র থেকে is.vector, আমরা যে খুঁজে পেয়েছেন:

is.vectorআয় TRUEযদি এক্স নিদিষ্ট কোন বৈশিষ্ট্যাবলী থাকার মোডের একটি ভেক্টর হয় নাম ছাড়া অন্য । এটি FALSEঅন্যথায় ফিরে আসে ।

আমি @ জাপের উত্তর থেকে নমুনা ডেটা ব্যবহার করছি , যেখানে বছরের কলামগুলির মানগুলি factor

এই stackপদ্ধতিটি এখানে :

cbind(wide[1:2], stack(lapply(wide[-c(1, 2)], as.character)))
##    Code     Country values  ind
## 1   AFG Afghanistan 20,249 1950
## 2   ALB     Albania  8,097 1950
## 3   AFG Afghanistan 21,352 1951
## 4   ALB     Albania  8,986 1951
## 5   AFG Afghanistan 22,532 1952
## 6   ALB     Albania 10,058 1952
## 7   AFG Afghanistan 23,557 1953
## 8   ALB     Albania 11,123 1953
## 9   AFG Afghanistan 24,555 1954
## 10  ALB     Albania 12,246 1954

11

এখানে ব্যবহার দেখাচ্ছে অন্য একটি উদাহরণ gatherথেকে tidyr। আপনি কলামগুলি gatherপৃথকভাবে মুছে ফেলার মাধ্যমে (যেমন আমি এখানে করি) বা আপনি যে বছরগুলি স্পষ্টভাবে চান তা অন্তর্ভুক্ত করে নির্বাচন করতে পারেন।

মনে রাখবেন যে, কমা হ্যান্ডেল করতে (এবং এক্স যদি যোগ check.names = FALSEসেট না করা হয়), আমি ব্যবহার করছি dplyr's এর সাথে পরিবর্তন ঘটান parse_numberথেকে readrটেক্সট মান নম্বরে ব্যাক রূপান্তর করবে। এগুলি সমস্ত অংশ tidyverseএবং তাই এক সাথে লোড করা যায়library(tidyverse)

wide %>%
  gather(Year, Value, -Code, -Country) %>%
  mutate(Year = parse_number(Year)
         , Value = parse_number(Value))

রিটার্নস:

   Code     Country Year Value
1   AFG Afghanistan 1950 20249
2   ALB     Albania 1950  8097
3   AFG Afghanistan 1951 21352
4   ALB     Albania 1951  8986
5   AFG Afghanistan 1952 22532
6   ALB     Albania 1952 10058
7   AFG Afghanistan 1953 23557
8   ALB     Albania 1953 11123
9   AFG Afghanistan 1954 24555
10  ALB     Albania 1954 12246

4

এখানে একটি সমাধান:

sqldf("Select Code, Country, '1950' As Year, `1950` As Value From wide
        Union All
       Select Code, Country, '1951' As Year, `1951` As Value From wide
        Union All
       Select Code, Country, '1952' As Year, `1952` As Value From wide
        Union All
       Select Code, Country, '1953' As Year, `1953` As Value From wide
        Union All
       Select Code, Country, '1954' As Year, `1954` As Value From wide;")

সবকিছুতে টাইপ না করেই ক্যোয়ারী তৈরি করতে, আপনি নিম্নলিখিতটি ব্যবহার করতে পারেন:

এটি বাস্তবায়নের জন্য জি। গ্রোথেন্ডিককে ধন্যবাদ ।

ValCol <- tail(names(wide), -2)

s <- sprintf("Select Code, Country, '%s' As Year, `%s` As Value from wide", ValCol, ValCol)
mquery <- paste(s, collapse = "\n Union All\n")

cat(mquery) #just to show the query
 #> Select Code, Country, '1950' As Year, `1950` As Value from wide
 #>  Union All
 #> Select Code, Country, '1951' As Year, `1951` As Value from wide
 #>  Union All
 #> Select Code, Country, '1952' As Year, `1952` As Value from wide
 #>  Union All
 #> Select Code, Country, '1953' As Year, `1953` As Value from wide
 #>  Union All
 #> Select Code, Country, '1954' As Year, `1954` As Value from wide

sqldf(mquery)
 #>    Code     Country Year  Value
 #> 1   AFG Afghanistan 1950 20,249
 #> 2   ALB     Albania 1950  8,097
 #> 3   AFG Afghanistan 1951 21,352
 #> 4   ALB     Albania 1951  8,986
 #> 5   AFG Afghanistan 1952 22,532
 #> 6   ALB     Albania 1952 10,058
 #> 7   AFG Afghanistan 1953 23,557
 #> 8   ALB     Albania 1953 11,123
 #> 9   AFG Afghanistan 1954 24,555
 #> 10  ALB     Albania 1954 12,246

দুর্ভাগ্যক্রমে, আমি তা মনে করি না PIVOTএবং এর UNPIVOTজন্য কাজ করব R SQLite। আপনি যদি নিজের জিজ্ঞাসাকে আরও পরিশীলিত পদ্ধতিতে লিখতে চান তবে আপনি এই পোস্টগুলি একবার দেখে নিতে পারেন:

ব্যবহার sprintfSQL কোয়্যারিগুলোকে আপ লেখার    বা    পাস ভেরিয়েবলsqldf


0

আপনি cdataপ্যাকেজটিও ব্যবহার করতে পারেন , যা (রূপান্তর) নিয়ন্ত্রণ সারণীর ধারণাটি ব্যবহার করে:

# data
wide <- read.table(text="Code Country        1950    1951    1952    1953    1954
AFG  Afghanistan    20,249  21,352  22,532  23,557  24,555
ALB  Albania        8,097   8,986   10,058  11,123  12,246", header=TRUE, check.names=FALSE)

library(cdata)
# build control table
drec <- data.frame(
    Year=as.character(1950:1954),
    Value=as.character(1950:1954),
    stringsAsFactors=FALSE
)
drec <- cdata::rowrecs_to_blocks_spec(drec, recordKeys=c("Code", "Country"))

# apply control table
cdata::layout_by(drec, wide)

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

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.