เคล็ดลับ R ที่มีประโยชน์ที่สุดคืออะไร? [ปิด]


88

หากต้องการแบ่งปันคำแนะนำและเคล็ดลับเพิ่มเติมสำหรับRคุณลักษณะหรือเคล็ดลับเดียวที่มีประโยชน์ที่สุดของคุณคืออะไร? เวกเตอร์ฉลาด? อินพุต / เอาต์พุตข้อมูล? การแสดงภาพและกราฟิก? การวิเคราะห์ทางสถิติ? ฟังก์ชั่นพิเศษ? สภาพแวดล้อมแบบโต้ตอบเอง?

หนึ่งรายการต่อโพสต์และเราจะดูว่าเราได้ผู้ชนะด้วยการโหวตหรือไม่

[แก้ไข 25- ส.ค. 2551]: หลังจากนั้นหนึ่งสัปดาห์ดูเหมือนว่าผู้str()ชนะจะได้รับการหยั่งเสียง ตามที่ฉันต้องการแนะนำตัวเองมันเป็นคำตอบที่ง่ายที่จะยอมรับ


8
@ เดิร์ก: "community wiki" หมายถึง "ชุมชนเป็นเจ้าของ" ไม่ใช่คำพ้องความหมายของ "คำถามแบบสำรวจความคิดเห็น" อย่าฟังตำรวจวิกิชุมชน
Juliet


8
CW กลั่นแกล้งอีกแล้ว. ฉันจะดู meta-SO ของคุณและจะเพิ่มคุณ: meta.stackexchange.com/questions/392/…
ars

13
@ars: คำถามที่ไม่มีคำตอบที่ชัดเจน Ergo ทำให้ CW
dmckee --- อดีตผู้ดูแลลูกแมว

2
@JD คอมเม้นยาว ๆ ฮา ๆ . น่าเสียดายที่มันซ่อนอยู่หลังฝาพับ ฉันหมายถึงการตอบคำถาม R ยาก ๆ ไม่ได้จ่ายสแต็กซ้ำ ดังนั้นมันก็โอเคสำหรับฉันถ้าผู้ชายที่ตั้งคำถามดีๆที่ทำให้ R บนแผนที่ได้รับเครดิตในที่สุด นอกจากนี้ยังมีประโยชน์มากกว่าผู้ใช้ R มากกว่าคำถามเคล็ดลับ C ที่คุณชื่นชอบสำหรับโปรแกรมเมอร์ C ...
Matt Bannert

คำตอบ:


64

str() บอกโครงสร้างของวัตถุใด ๆ


Python ใช้dir()- เหมาะสมกว่า
Hamish Grubijan

17
อาstrยังย่อมาจากstringหลายภาษา
Hamish Grubijan

ทำไมไม่class()? ดูเหมือนว่าจะเปิดเผยข้อมูลประเภทเดียวกัน เหตุใดจึงมีสองคำสั่งที่คล้ายกัน
hhh

1
class()เป็นเพียงส่วนเล็ก ๆ ของข้อมูลที่str()แสดง
hadley

64

ฟังก์ชันที่มีประโยชน์อย่างหนึ่งที่ฉันมักใช้คือ dput () ซึ่งช่วยให้คุณสามารถถ่ายโอนวัตถุในรูปแบบของรหัส R

# Use the iris data set
R> data(iris)
# dput of a numeric vector
R> dput(iris$Petal.Length)
c(1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5, 1.4, 1.5, 1.5, 1.6, 
1.4, 1.1, 1.2, 1.5, 1.3, 1.4, 1.7, 1.5, 1.7, 1.5, 1, 1.7, 1.9, 
1.6, 1.6, 1.5, 1.4, 1.6, 1.6, 1.5, 1.5, 1.4, 1.5, 1.2, 1.3, 1.4, 
1.3, 1.5, 1.3, 1.3, 1.3, 1.6, 1.9, 1.4, 1.6, 1.4, 1.5, 1.4, 4.7, 
4.5, 4.9, 4, 4.6, 4.5, 4.7, 3.3, 4.6, 3.9, 3.5, 4.2, 4, 4.7, 
3.6, 4.4, 4.5, 4.1, 4.5, 3.9, 4.8, 4, 4.9, 4.7, 4.3, 4.4, 4.8, 
5, 4.5, 3.5, 3.8, 3.7, 3.9, 5.1, 4.5, 4.5, 4.7, 4.4, 4.1, 4, 
4.4, 4.6, 4, 3.3, 4.2, 4.2, 4.2, 4.3, 3, 4.1, 6, 5.1, 5.9, 5.6, 
5.8, 6.6, 4.5, 6.3, 5.8, 6.1, 5.1, 5.3, 5.5, 5, 5.1, 5.3, 5.5, 
6.7, 6.9, 5, 5.7, 4.9, 6.7, 4.9, 5.7, 6, 4.8, 4.9, 5.6, 5.8, 
6.1, 6.4, 5.6, 5.1, 5.6, 6.1, 5.6, 5.5, 4.8, 5.4, 5.6, 5.1, 5.1, 
5.9, 5.7, 5.2, 5, 5.2, 5.4, 5.1)
# dput of a factor levels
R> dput(levels(iris$Species))
c("setosa", "versicolor", "virginica")

การโพสต์ส่วนข้อมูลที่ทำซ้ำได้ง่ายจะมีประโยชน์มากเมื่อคุณขอความช่วยเหลือหรือแก้ไขหรือจัดลำดับระดับของปัจจัยใหม่


42

head () และ tail () เพื่อรับส่วนแรกและส่วนสุดท้ายของ dataframe, vector, matrix, function ฯลฯ โดยเฉพาะอย่างยิ่งกับ data frames ขนาดใหญ่นี่เป็นวิธีที่รวดเร็วในการตรวจสอบว่าโหลดเรียบร้อยแล้ว


38

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

เป็นตัวอย่างง่ายๆให้พิจารณาการเข้าถึงนี้สำหรับ N = 10 จำนวนเต็มสุ่มระหว่าง min = 100 และ max = 200 จากrandom.org (ซึ่งให้ตัวเลขสุ่มจริงตามเสียงรบกวนในบรรยากาศแทนที่จะเป็นตัวสร้างตัวเลขสุ่มหลอก):

R> site <- "http://random.org/integers/"         # base URL
R> query <- "num=10&min=100&max=200&col=2&base=10&format=plain&rnd=new"
R> txt <- paste(site, query, sep="?")            # concat url and query string
R> nums <- read.table(file=txt)                  # and read the data
R> nums                                          # and show it
   V1  V2
1 165 143
2 107 118
3 103 132
4 191 100
5 138 185
R>

เช่นกันที่สุ่มแพคเกจให้ฟังก์ชั่นอำนวยความสะดวกหลายอย่างสำหรับการเข้าถึงrandom.org


BTW - ฉันขอแนะนำว่าคุณควรสร้าง CW selfanswers ถ้า (1) คุณโพสต์ทันทีและ (2) คุณไม่ได้ตั้งคำถาม CW มิฉะนั้นดูเหมือนว่าคุณกำลังพยายามเล่นเกมระบบตัวแทน YMMV และทั้งหมดนั้น
dmckee --- อดีตผู้ดูแลลูกแมว

1
ไม่ใช่การเล่นเกมระบบเพียงแค่เริ่มต้นสิ่งต่างๆ เขายังคงมีอิสระที่จะยอมรับคำตอบอื่น ๆ
อา

2
@ars: เขามีอิสระที่จะยอมรับสิ่งนี้ ฉันจะไม่พยายามบังคับให้เขาใช้วิกิถ้าเขาชนะอย่ารับคำแนะนำของฉัน แต่ฉันจะไม่โพสต์ selfanswer ที่เตรียมไว้โดยไม่ทำเครื่องหมายบน wiki และฉันจะไม่ลงคะแนนให้หากไม่มีมัน รับสิ่งที่คุ้มค่า
dmckee --- อดีตผู้ดูแลลูกแมว

4
@ เดิร์ก: เป็นที่ยอมรับทั้งหมดแม้จะได้รับการสนับสนุนจากเจฟฟ์และโจเอลให้ตอบคำถามของคุณเอง ไม่มีข้อกำหนดใด ๆ แม้แต่อย่างไม่เป็นทางการเพื่อให้คำตอบของคุณ CW คุณไม่ได้เล่นเกมกับระบบอย่างชัดเจน อีกครั้งอย่าสนใจตำรวจวิกิชุมชน
Juliet

8
ฉันต้องยอมรับว่าจุดประสงค์ส่วนหนึ่งของไซต์คือการให้คำตอบที่ดีที่สุดสำหรับปัญหาทั่วไปและแหล่งข้อมูลทั่วไป การตั้งคำถามและให้คำตอบที่ดีสามารถช่วยหนุนหัวข้อได้ สิ่งนี้มีประโยชน์อย่างยิ่งกับแท็กใหม่ / เล็กเช่น R.
kpierce8

35

ฉันพบว่าฉันกำลังใช้with()และwithin()มากขึ้นเรื่อย ๆ ไม่ต้อง$ทิ้งรหัสของฉันอีกต่อไปและไม่จำเป็นต้องเริ่มติดวัตถุเข้ากับเส้นทางการค้นหา อย่างจริงจังฉันพบว่าwith()ฯลฯ ทำให้ความตั้งใจของสคริปต์การวิเคราะห์ข้อมูลของฉันชัดเจนขึ้นมาก

> df <- data.frame(A = runif(10), B = rnorm(10))
> A <- 1:10 ## something else hanging around...
> with(df, A + B) ## I know this will use A in df!
 [1]  0.04334784 -0.40444686  1.99368816  0.13871605 -1.17734837
 [6]  0.42473812  2.33014226  1.61690799  1.41901860  0.8699079

with()ตั้งค่าสภาพแวดล้อมที่มีการประเมินนิพจน์ R within()ทำสิ่งเดียวกัน แต่อนุญาตให้คุณแก้ไขออบเจ็กต์ข้อมูลที่ใช้สร้างสภาพแวดล้อม

> df <- within(df, C <- rpois(10, lambda = 2))
> head(df)
           A          B C
1 0.62635571 -0.5830079 1
2 0.04810539 -0.4525522 1
3 0.39706979  1.5966184 3
4 0.95802501 -0.8193090 2
5 0.76772541 -1.9450738 2
6 0.21335006  0.2113881 4

สิ่งที่ฉันไม่ทราบเมื่อใช้ครั้งแรกwithin()คือคุณต้องทำการมอบหมายซึ่งเป็นส่วนหนึ่งของนิพจน์ที่ประเมินและกำหนดอ็อบเจ็กต์ที่ส่งคืน (ตามด้านบน) เพื่อให้ได้เอฟเฟกต์ที่ต้องการ


34

เคล็ดลับการป้อนข้อมูล = แพ็คเกจ RGoogleDocs

http://www.omegahat.org/RGoogleDocs/

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

# Get data from google spreadsheet
library(RGoogleDocs)
ps <-readline(prompt="get the password in ")
auth = getGoogleAuth("me@gmail.com", ps, service="wise")
sheets.con <- getGoogleDocsConnection(auth)
ts2=getWorksheets("Data Collection Repos",sheets.con)
names(ts2)
init.consent <-sheetAsMatrix(ts2$Sheet1,header=TRUE, as.data.frame=TRUE, trim=TRUE)

ฉันจำไม่ได้ว่าคำสั่งใด แต่หนึ่งหรือสองคำสั่งต่อไปนี้ใช้เวลาหลายวินาที

  1. getGoogleAuth

  2. getGoogleDocsConnection

  3. getWorksheets


27

ใช้ backticks เพื่ออ้างอิงชื่อที่ไม่ได้มาตรฐาน

> df <- data.frame(x=rnorm(5),y=runif(5))
> names(df) <- 1:2
> df
           1         2
1 -1.2035003 0.6989573
2 -1.2146266 0.8272276
3  0.3563335 0.0947696
4 -0.4372646 0.9765767
5 -0.9952423 0.6477714
> df$1
Error: unexpected numeric constant in "df$1"
> df$`1`
[1] -1.2035003 -1.2146266  0.3563335 -0.4372646 -0.9952423

ในกรณีนี้ df [, "1"] ก็ใช้ได้เช่นกัน แต่เห็บกลับทำงานในสูตร!

> lm(`2`~`1`,data=df)

Call:
lm(formula = `2` ~ `1`, data = df)

Coefficients:
(Intercept)          `1`  
     0.4087      -0.3440  

[แก้ไข] เดิร์กถามว่าทำไมถึงตั้งชื่อไม่ถูกต้อง? ไม่รู้สิ! แต่ฉันพบปัญหานี้ในทางปฏิบัติบ่อยพอสมควร ตัวอย่างเช่นการใช้แพ็คเกจการปรับรูปร่างของ Hadley:

> library(reshape)
> df$z <- c(1,1,2,2,2)
> recast(df,z~.,id.var="z")
Aggregation requires fun.aggregate: length used as default
  z (all)
1 1     4
2 2     6
> recast(df,z~.,id.var="z")$(all)
Error: unexpected '(' in "recast(df,z~.,id.var="z")$("
> recast(df,z~.,id.var="z")$`(all)`
Aggregation requires fun.aggregate: length used as default
[1] 4 6

โอเค แต่ทำไมคุณต้องแทนที่ชื่อที่ถูกต้องตามหลักไวยากรณ์ (เช่น x หรือ y) ด้วยชื่อที่ไม่ถูกต้อง (เช่น 1 หรือ 2) ที่ต้องใช้แบ็กติก
Dirk Eddelbuettel

3
นอกจากนี้ยังมีประโยชน์read.tableเมื่อcheck.namesเป็นเท็จเช่นเมื่อคุณต้องการทำงานกับชื่อคอลัมน์เดิม
hadley

25

ไม่รู้ว่าสิ่งนี้เป็นที่รู้จักกันดีเพียงใด แต่สิ่งที่ฉันใช้ประโยชน์ได้อย่างแน่นอนคือความสามารถในการอ้างอิงของสภาพแวดล้อม

zz <- new.env()
zz$foo <- c(1,2,3,4,5)
changer <- function(blah) {
   blah$foo <- 5
}
changer(zz)
zz$foo

สำหรับตัวอย่างนี้มันไม่สมเหตุสมผลว่าทำไมมันถึงมีประโยชน์ แต่ถ้าคุณผ่านวัตถุขนาดใหญ่รอบ ๆ มันสามารถช่วยได้


23

สิ่งใหม่ที่ฉันชอบคือห้องสมุด foreach ช่วยให้คุณสามารถประยุกต์ใช้สิ่งต่างๆได้ดี แต่ด้วยไวยากรณ์ที่ค่อนข้างง่ายกว่า:

list_powers <- foreach(i = 1:100) %do% {
  lp <- x[i]^i
  return (lp)
}

ส่วนที่ดีที่สุดคือหากคุณกำลังทำบางสิ่งที่ต้องใช้เวลามากจริง ๆ คุณสามารถเปลี่ยนจาก%do%เป็น%dopar%(ด้วยไลบรารีแบ็กเอนด์ที่เหมาะสม) เพื่อทำการขนานกันได้ทันทีแม้จะข้ามคลัสเตอร์ก็ตาม เนียนมาก.


19

ฉันทำมากของการจัดการพื้นฐานของข้อมูลเพื่อให้ที่นี่เป็นสองในตัวฟังก์ชั่น ( เปลี่ยน , ส่วนย่อย ) และห้องสมุดหนึ่ง ( sqldf ) ที่ผมใช้ในชีวิตประจำวัน

สร้างข้อมูลการขายตัวอย่าง

sales <- expand.grid(country = c('USA', 'UK', 'FR'),
                     product = c(1, 2, 3))
sales$revenue <- rnorm(dim(sales)[1], mean=100, sd=10)

> sales
  country product   revenue
1     USA       1 108.45965
2      UK       1  97.07981
3      FR       1  99.66225
4     USA       2 100.34754
5      UK       2  87.12262
6      FR       2 112.86084
7     USA       3  95.87880
8      UK       3  96.43581
9      FR       3  94.59259

ใช้ transform () เพื่อเพิ่มคอลัมน์

## transform currency to euros
usd2eur <- 1.434
transform(sales, euro = revenue * usd2eur)

>
  country product   revenue     euro
1     USA       1 108.45965 155.5311
2      UK       1  97.07981 139.2125
3      FR       1  99.66225 142.9157
...

ใช้ชุดย่อย () เพื่อแบ่งส่วนข้อมูล

subset(sales, 
       country == 'USA' & product %in% c(1, 2), 
       select = c('product', 'revenue'))

>
  product  revenue
1       1 108.4597
4       2 100.3475

ใช้ sqldf () เพื่อแบ่งส่วนและรวมกับ SQL

แพคเกจ sqldfมีอินเตอร์เฟซ SQL เพื่อเฟรมข้อมูล R

##  recast the previous subset() expression in SQL
sqldf('SELECT product, revenue FROM sales \
       WHERE country = "USA" \
       AND product IN (1,2)')

>
  product  revenue
1       1 108.4597
2       2 100.3475

ทำการรวมหรือ GROUP BY

sqldf('select country, sum(revenue) revenue \ 
       FROM sales \
       GROUP BY country')

>
  country  revenue
1      FR 307.1157
2      UK 280.6382
3     USA 304.6860

สำหรับฟังก์ชันการทำงานคล้ายแผนที่ลดขนาดที่ซับซ้อนยิ่งขึ้นบนเฟรมข้อมูลโปรดดูแพ็คเกจplyr และถ้าพบว่าตัวเองต้องการที่จะดึงผมออกผมขอแนะนำให้ตรวจสอบจากการจัดการข้อมูลกับ R


18
?ave

ชุดย่อยของ 'x []' เป็นค่าเฉลี่ยโดยที่แต่ละชุดย่อยประกอบด้วยการสังเกตที่มีระดับปัจจัยเดียวกัน การใช้งาน: ave (x, ... , FUN = mean)

ฉันจะใช้มันตลอดเวลา. (เช่นในคำตอบนี้ที่นี่ )


สิ่งนี้แตกต่างจาก tapply อย่างไร (x, factor, fun) ??
TMS

1
@Tomas ave รักษาการสั่งซื้อและความยาว ตัวอย่างเช่นคุณสามารถเพิ่มเวกเตอร์ของวิธีการกลุ่มลงในชุดข้อมูลได้ในขั้นตอนเดียว
Eduardo Leoni

18

วิธีเพิ่มความเร็วโค้ดและกำจัดลูป

แทนที่จะเป็นลูปที่วนลูปผ่านดาต้าเฟรมที่มองหาค่า เพียงแค่ใช้ส่วนย่อยของ df กับค่าเหล่านั้นเร็วกว่ามาก

แทนที่จะเป็น:

for(i in 1:nrow(df)){
  if (df$column[i] == x) {
    df$column2[i] <- y
    or any other similiar code
  }
}

ทำสิ่งนี้:

df$column2[df$column1 == x] <- y

แนวคิดพื้นฐานนั้นใช้ได้บ่อยมากและเป็นวิธีที่ดีในการกำจัดลูป


11
มีกับดักเล็ก ๆ อยู่ที่นี่ซึ่งใช้จับฉันตลอดเวลา หาก DF $ column1 มีค่า NA, Subsetting ใช้ == จะดึงออกค่าใด ๆ ที่เท่ากับ x และ NAS ใด ๆ เพื่อหลีกเลี่ยงปัญหานี้ให้ใช้ "% in%" แทน "=="
Matt Parker

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

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

16

บางครั้งคุณต้องrbindใช้ข้อมูลหลายเฟรม do.call()จะปล่อยให้คุณทำอย่างนั้น (มีคนอธิบายเรื่องนี้กับฉันเมื่อฉันผูกมัดฉันถามคำถามนี้เนื่องจากดูเหมือนจะไม่เป็นการใช้งานที่ชัดเจน)

foo <- list()

foo[[1]] <- data.frame(a=1:5, b=11:15)
foo[[2]] <- data.frame(a=101:105, b=111:115)
foo[[3]] <- data.frame(a=200:210, b=300:310)

do.call(rbind, foo)

โทรดี: unsplitผมพบว่านี้มักจะง่ายกว่าการใช้
Richie Cotton

16

ในการเขียนโปรแกรม R (ไม่ใช่เซสชันแบบโต้ตอบ) ฉันใช้ if (bad.condition) stop("message")มาก ทุกฟังก์ชั่นเริ่มต้นด้วยสิ่งเหล่านี้และเมื่อฉันทำงานผ่านการคำนวณฉันก็ใส่สิ่งเหล่านี้เข้าไปด้วย ฉันเดาว่าฉันติดนิสัยจากการใช้assert()ใน C ประโยชน์คือสองเท่า อย่างแรกการรับรหัสที่ใช้งานได้เร็วขึ้นมากเมื่อใช้การตรวจสอบเหล่านี้ ประการที่สองและอาจสำคัญกว่านั้นการทำงานกับโค้ดที่มีอยู่นั้นง่ายกว่ามากเมื่อคุณเห็นการตรวจสอบเหล่านี้บนทุกหน้าจอในตัวแก้ไขของคุณ คุณจะไม่ต้องสงสัยว่าx>0หรือเชื่อถือความคิดเห็นที่ระบุว่าเป็น ... คุณจะรู้ได้ทันทีว่ามันคืออะไร

ปล. โพสต์แรกของฉันที่นี่ อ่อนโยน!


12
ไม่ใช่นิสัยที่ไม่ดีและ R ยังเสนออีกวิธีหนึ่ง: stopfifnot(!bad.condition)ซึ่งกระชับกว่า
Dirk Eddelbuettel

13

traceback()ฟังก์ชั่นเป็นต้องเมื่อคุณมีที่ไหนสักแห่งความผิดพลาดและไม่เข้าใจมันได้อย่างง่ายดาย มันจะพิมพ์ร่องรอยของสแต็กซึ่งมีประโยชน์มากเนื่องจาก R ไม่ละเอียดมากโดยค่าเริ่มต้น

แล้วการตั้งค่า options(error=recover)จะช่วยให้คุณ "เข้าสู่" ฟังก์ชั่นที่เพิ่มข้อผิดพลาดและพยายามทำความเข้าใจว่าเกิดอะไรขึ้นราวกับว่าคุณสามารถควบคุมได้อย่างสมบูรณ์และสามารถใส่browser()ไปได้

ฟังก์ชันทั้งสามนี้สามารถช่วยในการดีบักโค้ดของคุณได้


1
options(error=recover)เป็นวิธีการดีบักที่ฉันชอบที่สุด
Joshua Ulrich

12

ฉันแปลกใจจริงๆที่ไม่มีใครโพสต์เกี่ยวกับการใช้การแตะการใช้งานและการพัฒนา กฎทั่วไปที่ฉันใช้เมื่อทำสิ่งต่างๆใน R คือถ้าฉันมี for loop ที่กำลังประมวลผลข้อมูลหรือการจำลองฉันจะพยายามแยกตัวประกอบและแทนที่ด้วย * apply บางคนไม่สนใจฟังก์ชั่น * ใช้เพราะพวกเขาคิดว่าฟังก์ชันพารามิเตอร์เดียวเท่านั้นที่สามารถส่งผ่านได้ไม่มีอะไรเพิ่มเติมจากความจริง! เช่นเดียวกับการส่งผ่านฟังก์ชันที่มีพารามิเตอร์เป็นออบเจ็กต์ชั้นหนึ่งใน Javascript คุณทำสิ่งนี้ใน R ด้วยฟังก์ชันที่ไม่ระบุชื่อ ตัวอย่างเช่น:

 > sapply(rnorm(100, 0, 1), round)
  [1]  1  1  0  1  1 -1 -2  0  2  2 -2 -1  0  1 -1  0  1 -1  0 -1  0  0  0  0  0
 [26]  2  0 -1 -2  0  0  1 -1  1  5  1 -1  0  1  1  1  2  0 -1  1 -1  1  0 -1  1
 [51]  2  1  1 -2 -1  0 -1  2 -1  1 -1  1 -1  0 -1 -2  1  1  0 -1 -1  1  1  2  0
 [76]  0  0  0 -2 -1  1  1 -2  1 -1  1  1  1  0  0  0 -1 -3  0 -1  0  0  0  1  1


> sapply(rnorm(100, 0, 1), round(x, 2)) # How can we pass a parameter?
Error in match.fun(FUN) : object 'x' not found


# Wrap your function call in an anonymous function to use parameters
> sapply(rnorm(100, 0, 1), function(x) {round(x, 2)})
  [1] -0.05 -1.74 -0.09 -1.23  0.69 -1.43  0.76  0.55  0.96 -0.47 -0.81 -0.47
 [13]  0.27  0.32  0.47 -1.28 -1.44 -1.93  0.51 -0.82 -0.06 -1.41  1.23 -0.26
 [25]  0.22 -0.04 -2.17  0.60 -0.10 -0.92  0.13  2.62  1.03 -1.33 -1.73 -0.08
 [37]  0.45 -0.93  0.40  0.05  1.09 -1.23 -0.35  0.62  0.01 -1.08  1.70 -1.27
 [49]  0.55  0.60 -1.46  1.08 -1.88 -0.15  0.21  0.06  0.53 -1.16 -2.13 -0.03
 [61]  0.33 -1.07  0.98  0.62 -0.01 -0.53 -1.17 -0.28 -0.95  0.71 -0.58 -0.03
 [73] -1.47 -0.75 -0.54  0.42 -1.63  0.05 -1.90  0.40 -0.01  0.14 -1.58  1.37
 [85] -1.00 -0.90  1.69 -0.11 -2.19 -0.74  1.34 -0.75 -0.51 -0.99 -0.36 -1.63
 [97] -0.98  0.61  1.01  0.55

# Note that anonymous functions aren't being called, but being passed.
> function() {print('hello #rstats')}()
function() {print('hello #rstats')}()
> a = function() {print('hello #rstats')}
> a
function() {print('hello #rstats')}
> a()
[1] "hello #rstats"

(สำหรับผู้ที่ติดตาม #rstats ฉันโพสต์สิ่งนี้ไว้ที่นั่นด้วย)

จำไว้ว่าใช้ Apply, sapply, lapply, tapply และ do.call! ใช้ประโยชน์จากเวกเตอร์ของ R คุณไม่ควรเดินขึ้นไปที่รหัส R จำนวนมากและดู:

N = 10000
l = numeric()
for (i in seq(1:N)) {
    sim <- rnorm(1, 0, 1)
    l <- rbind(l, sim)
}

สิ่งนี้ไม่เพียง แต่จะไม่เป็นเวกเตอร์ แต่โครงสร้างอาร์เรย์ใน R ไม่ได้เติบโตขึ้นเหมือนใน Python (เพิ่มขนาดเป็นสองเท่าเมื่อพื้นที่หมด IIRC) ดังนั้นแต่ละขั้นตอน rbind จะต้องเติบโต l พอที่จะยอมรับผลลัพธ์จาก rbind () ก่อนจากนั้นคัดลอกเนื้อหาของ l ก่อนหน้าทั้งหมด เพื่อความสนุกสนานลองใช้ข้างต้นใน R สังเกตว่าใช้เวลานานแค่ไหน (คุณไม่จำเป็นต้องใช้ Rprof หรือฟังก์ชันจับเวลาใด ๆ ) แล้วลอง

N=10000
l <- rnorm(N, 0, 1)

ต่อไปนี้ดีกว่าเวอร์ชันแรกด้วย:

N = 10000
l = numeric(N)
for (i in seq(1:N)) {
    sim <- rnorm(1, 0, 1)
    l[i] <- sim
}

ใช้ sapply, lapply และ tapply มีประโยชน์ หากคุณต้องการส่งผ่านพารามิเตอร์ไปยังฟังก์ชันที่มีชื่อเช่น round คุณสามารถส่งผ่านไปพร้อมกับใช้แทนการเขียนฟังก์ชันที่ไม่ระบุตัวตน ลองใช้ "sapply (rnorm (10, 0, 1), round, digit = 2)" ซึ่งแสดงผล "[1] -0.29 0.29 1.31 -0.06 -1.90 -0.84 0.21 0.02 0.23 -1.10"
Daniel

11

ตามคำแนะนำของ Dirk ฉันกำลังโพสต์ตัวอย่างเดียว ฉันหวังว่าพวกเขาจะไม่ "น่ารัก" เกินไป [ฉลาด แต่ฉันไม่สนใจ] หรือไม่สำคัญสำหรับผู้ชมกลุ่มนี้

แบบจำลองเชิงเส้นคือขนมปังและเนยของ R เมื่อจำนวนตัวแปรอิสระสูงตัวแปรหนึ่งมีสองทางเลือก ประการแรกคือใช้ lm.fit () ซึ่งรับเมทริกซ์การออกแบบ x และการตอบสนอง y เป็นอาร์กิวเมนต์เช่นเดียวกับ Matlab ข้อเสียเปรียบของแนวทางนี้คือค่าที่ส่งคืนเป็นรายการของวัตถุ (ค่าสัมประสิทธิ์ที่พอดีเศษซาก ฯลฯ ) ไม่ใช่วัตถุของคลาส "lm" ซึ่งสามารถสรุปได้อย่างสวยงามใช้สำหรับการทำนายการเลือกตามขั้นตอน ฯลฯ อย่างที่สอง แนวทางคือสร้างสูตร:

> A
           X1         X2          X3         X4         y
1  0.96852363 0.33827107 0.261332257 0.62817021 1.6425326
2  0.08012755 0.69159828 0.087994158 0.93780481 0.9801304
3  0.10167545 0.38119304 0.865209832 0.16501662 0.4830873
4  0.06699458 0.41756415 0.258071616 0.34027775 0.7508766
   ...

> (f=paste("y ~",paste(names(A)[1:4],collapse=" + ")))
[1] "y ~ X1 + X2 + X3 + X4"

> lm(formula(f),data=A)

Call:
lm(formula = formula(f), data = A)

Coefficients:
(Intercept)           X1           X2           X3           X4  
    0.78236      0.95406     -0.06738     -0.43686     -0.06644  

ถ้าคุณเลือกหนึ่งรายการต่อโพสต์และแสดงเป็นตัวอย่าง จากนั้นเราสามารถดำเนินการต่อไปได้หลายวันและโพสต์ตัวอย่างใหม่พร้อมคำสั่งใหม่ ... [BTW: อย่างที่ฉันจำได้คุณต้องใช้ as.formula (วาง (... )) สำหรับการใช้สูตร ]
Dirk Eddelbuettel

คุณไม่จำเป็นต้องสร้างสูตรอย่างชัดเจนเพื่อให้ครอบคลุมคอลัมน์ทั้งหมดเนื่องจากแบบฟอร์ม "y ~. - 1" ครอบคลุม "." หมายถึง 'คอลัมน์ทั้งหมดยกเว้นตัวแปรตามและ' - 1 'จะไม่รวมค่าคงที่ตามในตัวอย่างของคุณ
Dirk Eddelbuettel

ถูกต้องสำหรับตัวอย่างนี้ แต่สำหรับ X ที่มี ncols >> nrows ฉันมักจะลบตัวแปรอิสระบางตัวโดยเฉพาะในขั้นตอนสุดท้ายของการวิเคราะห์ ในกรณีนี้การสร้างสูตรจากชื่อกรอบข้อมูลยังคงสะดวก
gappy

10

คุณสามารถกำหนดค่าที่ส่งคืนจากบล็อก if-else

แทนที่จะเป็นเช่น

condition <- runif(1) > 0.5
if(condition) x <- 1 else x <- 2

คุณทำได้

x <- if(condition) 1 else 2

วิธีการทำงานนี้เป็นเวทมนตร์ที่ล้ำลึก


6
คุณยังทำได้เช่น x <- ifelse (เงื่อนไข 1, 2) ซึ่งในกรณีนี้แต่ละองค์ประกอบจะเป็นเวกเตอร์
เชน

Shane คุณทำได้ แต่ถ้าคุณไม่สนใจสิ่งที่ ifelse () ทำอย่างลึกซึ้งคุณอาจไม่ควรทำ! เป็นเรื่องง่ายที่จะเข้าใจผิด ...
Harlan

ขลังอะไรประมาณนั้น นั่นเป็นเพียงวิธีที่if-then-elseนิพจน์ทำงานในภาษาที่ใช้งานได้ (เพื่อไม่ให้สับสนกับif-then-else ข้อความ ) คล้ายกับตัว?:ดำเนินการตามท้ายของภาษาซีเหมือนกันมาก
Frank

10

ในฐานะที่เป็น noob ทั้งหมดสำหรับ R และมือใหม่ที่สถิติฉันรัก unclass() จะพิมพ์องค์ประกอบทั้งหมดของ data frame เป็นรายการธรรมดา

ค่อนข้างสะดวกสำหรับการดูชุดข้อมูลทั้งหมดในครั้งเดียวเพื่อแก้ไขปัญหาที่อาจเกิดขึ้นได้อย่างรวดเร็ว


9

CrossTable()จากgmodelsแพคเกจช่วยให้สามารถเข้าถึง crosstabs สไตล์ SAS และ SPSS พร้อมกับการทดสอบตามปกติ (Chisq, McNemar ฯลฯ ) โดยพื้นฐานแล้วมันxtabs()มีเอาต์พุตแฟนซีและการทดสอบเพิ่มเติมบางอย่าง - แต่จะทำให้การแบ่งปันผลลัพธ์กับคนต่างชาติง่ายขึ้น


ดี !! ฉันใช้ gmodels ค่อนข้างน้อย แต่พลาดอันนั้น
Abhijit

คำตอบที่ดีสิ่งที่สามารถทำให้ฉันห่างจากคำอธิบายตารางมากเกินไปกับพวกต่างศาสนาคือการใช้เวลาที่ดี
Stedy

7

system()แตกหัก เพื่อให้สามารถเข้าถึงเครื่องมือยูนิกซ์ทั้งหมด (อย่างน้อยก็ใน Linux / MacOSX) จากภายในสภาพแวดล้อม R ได้กลายเป็นสิ่งล้ำค่าอย่างรวดเร็วในขั้นตอนการทำงานประจำวันของฉัน


1
ที่เกี่ยวข้องกับความคิดเห็นก่อนหน้านี้ของฉันเกี่ยวกับการเชื่อมต่อ: คุณยังสามารถใช้ pipe () เพื่อส่งผ่านข้อมูลจากหรือไปยังคำสั่ง Unix ดูhelp(connections)รายละเอียดและตัวอย่าง
Dirk Eddelbuettel

6

นี่คือวิธีแก้ปัญหาที่น่ารำคาญในการแปลงปัจจัยเป็นตัวเลข (คล้ายกับข้อมูลประเภทอื่นเช่นกัน)

old.var <- as.numeric(levels(old.var))[as.numeric(old.var)]

2
บางทีคุณอาจหมายถึงเวกเตอร์ "เป็นตัวอักษร" ซึ่งในกรณีนี้ "as.character (old.var)" จะง่ายกว่า
Dirk Eddelbuettel

1
ฉันคิดเสมอว่าคำแนะนำนี้ (สามารถอ่านได้ที่? factor) ว่าจะเข้าใจผิด คุณต้องแน่ใจว่าแก่แล้ว var เป็นปัจจัยและสิ่งนี้จะแตกต่างกันไปตามตัวเลือกที่คุณตั้งไว้สำหรับเซสชัน R การใช้ as.numeric (as.character (old.var)) ทั้งปลอดภัยและสะอาดกว่า
Eduardo Leoni

จริงๆแล้วไม่คุ้มกับการโหวตลงคะแนน แต่อย่างใด สิ่งนี้ใช้ได้กับฉัน
Ryan R.Sosario

Ryan - คุณช่วยแก้ไขรหัสของคุณได้ไหม ถ้า old.var <- factor (1: 2); รหัสของคุณจะให้ [1] "1" "2" (ไม่ใช่ตัวเลข) บางทีคุณอาจหมายถึงเป็นตัวเลข (ระดับ (old.var) [old.var])?
Eduardo Leoni

3
หรือมีประสิทธิภาพมากกว่าเล็กน้อย:as.numeric(levels(old.var))[old.var]
hadley

6

แม้ว่าคำถามนี้ได้รับการขึ้นในขณะที่ฉันเพิ่งค้นพบเคล็ดลับที่ดีในSAS และ R บล็อกcutสำหรับการใช้คำสั่ง คำสั่งนี้ใช้เพื่อแบ่งข้อมูลออกเป็นหมวดหมู่และฉันจะใช้ชุดข้อมูลไอริสเป็นตัวอย่างและแบ่งออกเป็น 10 ประเภท:

> irisSL <- iris$Sepal.Length
> str(irisSL)
 num [1:150] 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
> cut(irisSL, 10)
  [1] (5.02,5.38] (4.66,5.02] (4.66,5.02] (4.3,4.66]  (4.66,5.02] (5.38,5.74] (4.3,4.66]  (4.66,5.02] (4.3,4.66]  (4.66,5.02]
 [11] (5.38,5.74] (4.66,5.02] (4.66,5.02] (4.3,4.66]  (5.74,6.1]  (5.38,5.74] (5.38,5.74] (5.02,5.38] (5.38,5.74] (5.02,5.38]
 [21] (5.38,5.74] (5.02,5.38] (4.3,4.66]  (5.02,5.38] (4.66,5.02] (4.66,5.02] (4.66,5.02] (5.02,5.38] (5.02,5.38] (4.66,5.02]
 [31] (4.66,5.02] (5.38,5.74] (5.02,5.38] (5.38,5.74] (4.66,5.02] (4.66,5.02] (5.38,5.74] (4.66,5.02] (4.3,4.66]  (5.02,5.38]
 [41] (4.66,5.02] (4.3,4.66]  (4.3,4.66]  (4.66,5.02] (5.02,5.38] (4.66,5.02] (5.02,5.38] (4.3,4.66]  (5.02,5.38] (4.66,5.02]
 [51] (6.82,7.18] (6.1,6.46]  (6.82,7.18] (5.38,5.74] (6.46,6.82] (5.38,5.74] (6.1,6.46]  (4.66,5.02] (6.46,6.82] (5.02,5.38]
 [61] (4.66,5.02] (5.74,6.1]  (5.74,6.1]  (5.74,6.1]  (5.38,5.74] (6.46,6.82] (5.38,5.74] (5.74,6.1]  (6.1,6.46]  (5.38,5.74]
 [71] (5.74,6.1]  (5.74,6.1]  (6.1,6.46]  (5.74,6.1]  (6.1,6.46]  (6.46,6.82] (6.46,6.82] (6.46,6.82] (5.74,6.1]  (5.38,5.74]
 [81] (5.38,5.74] (5.38,5.74] (5.74,6.1]  (5.74,6.1]  (5.38,5.74] (5.74,6.1]  (6.46,6.82] (6.1,6.46]  (5.38,5.74] (5.38,5.74]
 [91] (5.38,5.74] (5.74,6.1]  (5.74,6.1]  (4.66,5.02] (5.38,5.74] (5.38,5.74] (5.38,5.74] (6.1,6.46]  (5.02,5.38] (5.38,5.74]
[101] (6.1,6.46]  (5.74,6.1]  (6.82,7.18] (6.1,6.46]  (6.46,6.82] (7.54,7.9]  (4.66,5.02] (7.18,7.54] (6.46,6.82] (7.18,7.54]
[111] (6.46,6.82] (6.1,6.46]  (6.46,6.82] (5.38,5.74] (5.74,6.1]  (6.1,6.46]  (6.46,6.82] (7.54,7.9]  (7.54,7.9]  (5.74,6.1] 
[121] (6.82,7.18] (5.38,5.74] (7.54,7.9]  (6.1,6.46]  (6.46,6.82] (7.18,7.54] (6.1,6.46]  (5.74,6.1]  (6.1,6.46]  (7.18,7.54]
[131] (7.18,7.54] (7.54,7.9]  (6.1,6.46]  (6.1,6.46]  (5.74,6.1]  (7.54,7.9]  (6.1,6.46]  (6.1,6.46]  (5.74,6.1]  (6.82,7.18]
[141] (6.46,6.82] (6.82,7.18] (5.74,6.1]  (6.46,6.82] (6.46,6.82] (6.46,6.82] (6.1,6.46]  (6.46,6.82] (6.1,6.46]  (5.74,6.1] 
10 Levels: (4.3,4.66] (4.66,5.02] (5.02,5.38] (5.38,5.74] (5.74,6.1] (6.1,6.46] (6.46,6.82] (6.82,7.18] ... (7.54,7.9]

5

เคล็ดลับอีกประการหนึ่ง แพคเกจบางอย่างเช่น glmnet, เพียงใช้เป็นปัจจัยการผลิตเมทริกซ์ออกแบบและตัวแปรการตอบสนอง หากต้องการปรับโมเดลให้พอดีกับการโต้ตอบระหว่างคุณลักษณะทั้งหมดเธอจะใช้สูตร "y ~. ^ 2" ไม่ได้ การใช้expand.grid()ทำให้เราสามารถใช้ประโยชน์จากการจัดทำดัชนีอาร์เรย์และการดำเนินการเวกเตอร์ของ R ได้อย่างมีประสิทธิภาพ

interArray=function(X){
    n=ncol(X)
    ind=expand.grid(1:n,1:n)
    return(X[,ind[,1]]*X[,ind[,2]])
}

> X
          X1         X2
1 0.96852363 0.33827107
2 0.08012755 0.69159828
3 0.10167545 0.38119304
4 0.06699458 0.41756415
5 0.08187816 0.09805104

> interArray(X)
           X1          X2        X1.1        X2.1
1 0.938038022 0.327623524 0.327623524 0.114427316
2 0.006420424 0.055416073 0.055416073 0.478308177
3 0.010337897 0.038757974 0.038757974 0.145308137
4 0.004488274 0.027974536 0.027974536 0.174359821
5 0.006704033 0.008028239 0.008028239 0.009614007

3
หากฟังก์ชันการสร้างแบบจำลองไม่ยอมรับสูตร (ซึ่งหายากมาก!) จะไม่เป็นการดีกว่าที่จะสร้างเมทริกซ์การออกแบบด้วยmodel.matrixหรือไม่?
hadley

ทำได้ดีนี่. ฉันไม่รู้ถึงการมีอยู่ของฟังก์ชันนี้ ฟังก์ชันข้างต้นเทียบเท่ากับ model.matrix (~. ^ 2 -1, X) แต่เกี่ยวกับการส่งผ่านเมทริกซ์นอกเหนือจาก glmnet ฉันมักจะส่งตัวชี้อาร์เรย์ไปยังฟังก์ชัน C ที่กำหนดเอง อันที่จริงฉันไม่รู้ว่าจะส่งผ่านสูตรไปยังฟังก์ชันอย่างไร คุณมีตัวอย่างของเล่นหรือไม่?
gappy

5

หนึ่งที่ชื่นชอบของฉัน, เทคนิคหากไม่ได้ค่อนข้างคัมภีร์คือการใช้และeval() parse()ตัวอย่างนี้อาจแสดงให้เห็นว่าจะมีประโยชน์อย่างไร

NY.Capital <- 'Albany'
state <- 'NY'
parameter <- 'Capital'
eval(parse(text=paste(state, parameter, sep='.')))

[1] "Albany"

สถานการณ์ประเภทนี้เกิดขึ้นบ่อยกว่าไม่มากนักและการใช้eval()และparse()สามารถช่วยแก้ไขได้ แน่นอนฉันยินดีรับฟังความคิดเห็นเกี่ยวกับวิธีอื่น ๆ ในการเขียนโค้ดนี้


1
ซึ่งสามารถทำได้เช่นกันกับองค์ประกอบเวกเตอร์ที่มีชื่อ
Dirk Eddelbuettel

3
ห้องสมุด (โชคชะตา); โชคลาภ (106) หากคำตอบคือการแยกวิเคราะห์ () คุณควรคิดคำถามใหม่ - Thomas Lumley R-help (กุมภาพันธ์ 2548)
Eduardo Leoni

นี่คือตัวอย่างที่ eval () และ parse () มีประโยชน์ สิ่งนี้เกี่ยวข้องกับแพ็คเกจไบโอคอนดักเตอร์เช่น hgu133a.db และสถานที่ที่คุณพยายามหาข้อมูลเกี่ยวกับรหัสชุดโพรบเซ็ต ตัวอย่างเช่น: พารามิเตอร์ library (hgu133a.db) <- 'SYMBOL' mget ('202431_s_at', env = eval (แยกวิเคราะห์ (text = paste ('hgu133a', พารามิเตอร์, sep = ''))) พารามิเตอร์ <- 'ENTREZID 'mget (' 202431_s_at ', env = eval (แยกวิเคราะห์ (text = paste (' hgu133a ', parameter, sep =' ')))
andrewj

ดังที่ Dirk กล่าวว่าสิ่งนี้ทำได้ดีกว่าด้วยองค์ประกอบเวกเตอร์ที่มีชื่อหรือ `` get (paste (state, parameter, sep = '.'))
hadley

@Hadley ไม่รู้ว่าคุณสามารถใช้ get () แบบนั้นได้ ขอบคุณ.
andrewj

5

set.seed() ตั้งค่าสถานะตัวสร้างตัวเลขสุ่ม

ตัวอย่างเช่น:

> set.seed(123)
> rnorm(1)
[1] -0.5604756
> rnorm(1)
[1] -0.2301775
> set.seed(123)
> rnorm(1)
[1] -0.5604756

มีประโยชน์สุด ๆ กับตัวอย่างที่ใช้ฟังก์ชันสุ่ม ... ช่วยให้ทุกคนเข้าใจ
ตรงกัน

5

สำหรับผู้ที่กำลังเขียน C ที่จะเรียกจาก R: .Internal(inspect(...))นั้นมีประโยชน์ ตัวอย่างเช่น:

> .Internal(inspect(quote(a+2)))
  @867dc28 06 LANGSXP g0c0 [] 
  @8436998 01 SYMSXP g1c0 [MARK,gp=0x4000] "+"
  @85768b0 01 SYMSXP g1c0 [MARK,NAM(2)] "a"
  @8d7bf48 14 REALSXP g0c1 [] (len=1, tl=0) 2

4

d = '~ / R รหัส / ห้องสมุด /'

ไฟล์ = list.files (d, '. r $')

สำหรับ (f ในไฟล์) {if (! (f == 'mysource.r')) {print (paste ('Sourcing', f)) source (paste (d, f, sep = ''))}}

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

แหล่งที่มา ("~ / R Code / Library / mysource.r")


6
อย่าทำ เขียนแพ็คเกจ
Dirk Eddelbuettel

ขอบคุณ. ฉันได้ดูเธรดหนึ่งหรือสองหัวข้อเกี่ยวกับ roxygen และดูเหมือนว่าฉันอาจจะอยู่ในระดับที่ฉันควรลองเขียนแพ็คเกจการใช้งานด้วยตนเองง่ายๆ
mcheema

3

เพื่อดำเนินการกับตัวแปรหลายตัวในกรอบข้อมูล สิ่งนี้ถูกขโมยจาก subset.data.frame

get.vars<-function(vars,data){
    nl <- as.list(1L:ncol(data))
    names(nl) <- names(data)
    vars <- eval(substitute(vars), nl, parent.frame())
    data[,vars]
    #do stuff here
}

get.vars(c(cyl:hwy,class),mpg)

1
ตอนแรกดูเหมือนจะดูดี แต่รหัสประเภทนี้จะทำให้คุณไม่มีปัญหาในระยะยาว ชัดเจนกว่าเสมอ
hadley

ครวญเพลงฉันใช้เคล็ดลับนี้ค่อนข้างช้า คุณสามารถระบุเพิ่มเติมเกี่ยวกับปัญหาที่เกิดขึ้นได้หรือไม่?
Ian Fellows

บางที hadley แนะนำให้ใช้แพ็คเกจ plyr แทน?
Christopher DuBois

3
ไม่นี่ไม่ใช่คำแนะนำที่ถูกปิดบังให้ใช้ plyr แทน ปัญหาพื้นฐานเกี่ยวกับรหัสของคุณคือมันขี้เกียจทางความหมายแทนที่จะทำให้ผู้ใช้สะกดสิ่งที่ต้องการอย่างชัดเจนคุณต้องใช้ "เวทมนตร์" เพื่อเดา ปัญหาของสิ่งนี้คือมันทำให้ฟังก์ชันยากในการเขียนโปรแกรมด้วยนั่นคือมันยากที่จะเขียนฟังก์ชันที่เรียกget.varsโดยไม่ต้องกระโดดผ่านห่วงมากมาย
hadley

3

ฉันเคยโพสต์สิ่งนี้มาแล้วครั้งหนึ่ง แต่ฉันใช้มันมากฉันคิดว่าฉันจะโพสต์อีกครั้ง ฟังก์ชั่นเพียงเล็กน้อยในการส่งคืนชื่อและหมายเลขตำแหน่งของ data.frame ไม่มีอะไรพิเศษที่จะต้องแน่ใจ แต่ฉันแทบจะไม่เคยทำผ่านเซสชันโดยไม่ได้ใช้หลายครั้ง

##creates an object from a data.frame listing the column names and location

namesind = ฟังก์ชัน (df) {

temp1=names(df)
temp2=seq(1,length(temp1))
temp3=data.frame(temp1,temp2)
names(temp3)=c("VAR","COL")
return(temp3)
rm(temp1,temp2,temp3)

}

พรรณี <- namesind


4
นี่คือซับเดียวจริงๆ:data.frame(VAR = names(df), COL = seq_along(df))
hadley

สวยมากบางทีฉันจะเปลี่ยนเป็น ni <- function (df) {data.frame (VAR = names (df), COL = seq_along (df))}
kpierce8

1
ฉันใช้: data.frame (colnames (the.df))
Tal Galili
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.