เพิ่มความแตกต่างและเปอร์เซ็นต์การเปลี่ยนแปลงของทุกคอลัมน์ในกรอบข้อมูลหรือไม่

ฉันต้องการเพิ่มความแตกต่างและเปอร์เซ็นต์การเปลี่ยนแปลงให้กับทุกคอลัมน์ในดาต้าเฟรม

ฉันสามารถละลายข้อมูลและทำการคำนวณได้ แต่ไม่รู้ว่าจะแปลงหรือปรับรูปร่างกลับเข้าด้วยกันได้อย่างไร ฉันยังมีข้อสงสัยเล็กๆ น้อยๆ ว่าสิ่งนี้สามารถสำเร็จได้อย่างง่ายดายด้วย plyr แต่แถว n-1 ที่ส่งคืนโดย diff() ทำให้เกิดปัญหากับฉัน

การใช้ชุดข้อมูลที่รวมอยู่:

library(plyr)
library(quantmod)
head(longley)

     GNP.deflator     GNP Unemployed Armed.Forces Population Year Employed
1947         83.0 234.289      235.6        159.0    107.608 1947   60.323
1948         88.5 259.426      232.5        145.6    108.632 1948   61.122
1949         88.2 258.054      368.2        161.6    109.773 1949   60.171
1950         89.5 284.599      335.1        165.0    110.929 1950   61.187
1951         96.2 328.975      209.9        309.9    112.075 1951   63.221
1952         98.1 346.999      193.2        359.4    113.270 1952   63.639

longley.m <- melt(longley, id="Year")
longley.m <- ddply(longley.m, .(variable), transform, valdiff=diff(c(NA, value)), valdelt=Delt(value))

head(longley.m)

  Year     variable value valdiff Delt.1.arithmetic
1 1947 GNP.deflator  83.0      NA                NA
2 1948 GNP.deflator  88.5     5.5       0.066265060
3 1949 GNP.deflator  88.2    -0.3      -0.003389831
4 1950 GNP.deflator  89.5     1.3       0.014739229
5 1951 GNP.deflator  96.2     6.7       0.074860335
6 1952 GNP.deflator  98.1     1.9       0.019750520

(ฉันไม่รู้ว่าทำไม Delt ถึงสร้างชื่อคอลัมน์เป็นของตัวเอง แต่ฉันยอมแพ้แล้ว)

ตอนนี้ ฉันสามารถ cast(longley.m, Year ~ variable) เพื่อกลับไปยังชุดข้อมูลเดิมได้ แต่ฉันต้องการให้มีความแตกต่างและเปอร์เซ็นต์การเปลี่ยนแปลงสำหรับแต่ละตัวแปรในคอลัมน์ที่แตกต่างกัน โดยไม่ต้องทำการคำนวณด้วยตนเองกับตัวแปรแต่ละตัว จากนั้นจึงรวมกลับเข้าด้วยกัน ฉันค่อนข้างมั่นใจว่าฉันได้ลองนักแสดงทุกรูปแบบแล้ว แต่ก็ไม่ได้ผล...

อัปเดต: Joran แก้ไขปัญหาการตั้งชื่อคอลัมน์ Delt: บังคับด้วย as.vector!


person Totovader    schedule 01.01.2012    source แหล่งที่มา
comment
มันทำ? ปัญหาของฉันเกี่ยวกับการดำเนินการเดียวกันในทุกคอลัมน์และนำกลับเข้าไปในดาต้าเฟรม ฉันไม่เห็นวิธีแก้ปัญหาสำหรับสิ่งนั้นในนั้น   -  person Totovader    schedule 01.01.2012
comment
ฉันเดาว่าฉันไม่เข้าใจที่มาของความยากลำบาก ฉันเห็นสิ่งที่ฉันสามารถทำได้เพื่อยกเลิกการลงคะแนน   -  person IRTFM    schedule 01.01.2012


คำตอบ (3)


ฉันน่าจะเข้าใกล้สิ่งนี้มากกว่า @joran

แต่ถ้าคุณต้องการเดินทางต่อไปตามเส้นทางที่คุณอยู่ คุณสามารถใช้ reshape() จากฐาน R เพื่อสิ้นสุดการเดินทาง:

# Your code
library(plyr)
library(quantmod)
library(reshape)
head(longley)
longley.m <- melt(longley, id="Year")

# My addition
longley.m <- ddply(longley.m, .(variable), transform, 
                   valdiff = diff(c(NA, value)), 
                   valdelt = as.vector(Delt(value)))
reshape(longley.m, idvar="Year", timevar="variable", direction="wide")
person Josh O'Brien    schedule 01.01.2012
comment
ฉันคิดว่านี่ทำให้ฉันได้สิ่งที่ฉันกำลังมองหา ปรับรูปร่างไม่ได้คลิกสำหรับฉัน ขอบคุณ! - person Totovader; 01.01.2012
comment
เฮ้ ผู้คนจำนวนมากมีประสบการณ์เช่นนั้นกับ reshape - person IRTFM; 01.01.2012

สาเหตุของชื่อคอลัมน์แปลก ๆ เมื่อใช้ Delt คือส่งคืนเมทริกซ์ แทนที่จะเป็นเวกเตอร์ การบังคับมันด้วย as.vector จะช่วยไขปริศนานั้นได้

อย่างไรก็ตาม ฉันสงสัยว่าคุณกำลังทำให้เรื่องนี้ซับซ้อนเกินไป มีเหตุผลไหมที่คุณไม่สามารถจัดเรียงกรอบข้อมูลตามปี จากนั้นใช้ diff และ Delt กับแต่ละคอลัมน์ เปลี่ยนชื่อคอลัมน์ให้เหมาะสม จากนั้นจึง cbind เข้าด้วยกัน

รหัสเริ่มต้นบางส่วน:

longley.o <- arrange(longley,Year)
apply(longley.o,2,function(x){c(NA,diff(x))})
apply(longley.o,2,Delt)

เวอร์ชันที่สมบูรณ์ยิ่งขึ้น (ไม่มีการป้อนคอลัมน์ด้วยมือ):

longley.o <- arrange(longley,Year)
valdiff <- apply(longley.o,2,function(x){c(NA,diff(x))})
valdelt <- apply(longley.o,2,Delt)

colnames(valdiff) <- paste("valdiff",colnames(valdiff),sep = ".")
colnames(valdelt) <- paste("valdelt",colnames(valdelt),sep = ".")

out <- cbind(longley.o,
             valdiff[,-match("Year",colnames(longley.o))],
             valdelt[,-match("Year",colnames(longley.o))])
person joran    schedule 01.01.2012
comment
ขอบคุณสำหรับการไขปริศนาแรก! แม้ว่าฉันมักจะทำสิ่งที่ซับซ้อนมากเกินไป แต่ในกรณีนี้ ฉันรู้สึกว่าอย่างน้อยฉันก็มาถูกทางแล้ว ปัญหาในการทำ diff และ Delt ในแต่ละคอลัมน์ (ก่อนที่ฉันจะละลายมัน) คือฉันต้องการให้มันในแต่ละปีสำหรับแต่ละตัวแปร ฉันจะต้องป้อนแต่ละคอลัมน์ในโซลูชันของคุณอย่างชัดเจน ปัญหาจริงๆ ของฉันมีมากกว่า 20 คอลัมน์ใน dataframe ที่แตกต่างกันประมาณ 12 คอลัมน์ ดังนั้นฉันจึงมองหาวิธีแก้ปัญหาง่ายๆ - person Totovader; 01.01.2012
comment
@Totovader ฉันไม่ทำตามเหตุผลของคุณจริงๆ หากคุณต้องการใช้การปรับรูปร่างมากกว่า Josh ก็ช่วยคุณได้ การอัปเดตของฉันด้านบนควรให้ผลลัพธ์เหมือนกับคำตอบของเขา - person joran; 01.01.2012
comment
ฉันเห็นแล้วว่าคุณกำลังจะไปที่ไหน ตอนนี้ส่วนที่จับคู่ของส่วน cbind ของคุณนั้นแปลกสำหรับฉัน ดังนั้นมันคงเป็นขั้นตอนเพิ่มเติมเล็กน้อย - person Totovader; 01.01.2012
comment
ระวังการใช้นำไปใช้กับเฟรมข้อมูล - มันจะบังคับให้เมทริกซ์ - person hadley; 01.01.2012

ฉันคิดว่ากลยุทธ์การหลอมละลายและการประมวลผลภายในหมวดหมู่ของตัวบ่งชี้นั้นซับซ้อนโดยไม่จำเป็น หากคุณต้องการดาต้าเฟรมที่มีการเพิ่มแถวของ NA ไว้ที่จุดเริ่มต้น ดังนั้นมันจะจับคู่กับหมายเลขแถว ดังนั้นสองทางเลือกที่แนะนำตัวเองว่าเป็นซับเดียว:

as.data.frame( lapply(longley, function(x) c(NA, diff(x))))

หรือถ้าคุณรู้ว่ารายการทั้งหมดเป็นตัวเลข (ตามที่แนะนำโดยการใช้ฟังก์ชันตัวเลข) และดังนั้นจึงสามารถใช้ apply ได้ ดังนั้นแนวทางนี้จะง่ายกว่า:

apply(longley,2, FUN=function(x) c(NA, diff(x)))

และถ้าคุณต้องการสิ่งเหล่านี้ร่วมกับผลลัพธ์ Delt:

cbind(apply(longley,2, FUN=function(x) c(NA, diff(x))), 
      apply(longley,2, Delt) )
person IRTFM    schedule 01.01.2012