لدي عدد من الأعمدة التي أود إزالتها من إطار البيانات. أعلم أنه يمكننا حذفها بشكل فردي باستخدام شيء مثل:
df$x <- NULL
لكنني كنت آمل أن أفعل ذلك بأوامر أقل.
أعلم أيضًا أنه يمكنني إسقاط أعمدة باستخدام فهرسة عدد صحيح مثل هذا:
df <- df[ -c(1, 3:6, 12) ]
لكنني قلق من أن الوضع النسبي لمتغيراتي قد يتغير.
نظرًا لمدى قوة R ، فكنت أحسب أن هناك طريقة أفضل من إسقاط كل عمود واحد تلو الآخر.
يمكنك استخدام قائمة بسيطة من الأسماء:
DF <- data.frame(
x=1:10,
y=10:1,
z=rep(5,10),
a=11:20
)
drops <- c("x","z")
DF[ , !(names(DF) %in% drops)]
أو بدلاً من ذلك ، يمكنك إنشاء قائمة بأسماء هؤلاء الأشخاص للإبقاء عليهم والرجوع إليهم بالاسم:
keeps <- c("y", "a")
DF[keeps]
تحرير: بالنسبة لأولئك الذين لم يتعرفوا بعد على الوسيطة drop
الخاصة بوظيفة الفهرسة ، إذا كنت تريد الاحتفاظ بعمود واحد كإطار بيانات ، فأنت تقوم بما يلي:
keeps <- "y"
DF[ , keeps, drop = FALSE]
drop=TRUE
(أو عدم ذكرها) ستسقط أبعادًا غير ضرورية ، وبالتالي تُرجع متجهًا مع قيم العمود y
.
هناك أيضًا أمر subset
، مفيد إذا كنت تعرف الأعمدة التي تريدها:
df <- data.frame(a = 1:10, b = 2:11, c = 3:12)
df <- subset(df, select = c(a, c))
تم التحديث بعد تعليق بواسطةhadley: إلى إسقاط أعمدة ، يمكنك القيام بما يلي:
df <- subset(df, select = -c(a, c))
within(df, rm(x))
من الأسهل ، أو لمتغيرات متعددة:
within(df, rm(x, y))
أو إذا كنت تتعامل مع data.table
s (لكل كيف يمكنك حذف عمود حسب الاسم في data.table؟ ):
dt[, x := NULL] # Deletes column x by reference instantly.
dt[, !"x"] # Selects all but x into a new data.table.
أو لمتغيرات متعددة
dt[, c("x","y") := NULL]
dt[, !c("x", "y")]
يمكنك استخدام %in%
كما يلي:
df[, !(colnames(df) %in% c("x","bar","foo"))]
قائمة (فارغة) تعمل أيضا:
dat <- mtcars
colnames(dat)
# [1] "mpg" "cyl" "disp" "hp" "drat" "wt" "qsec" "vs" "am" "gear"
# [11] "carb"
dat[,c("mpg","cyl","wt")] <- list(NULL)
colnames(dat)
# [1] "disp" "hp" "drat" "qsec" "vs" "am" "gear" "carb"
هناك إستراتيجية محتملة أكثر استنادًا إلى حقيقة أن grep () سيعود متجهًا رقميًا. إذا كان لديك قائمة طويلة من المتغيرات كما أفعل في أحد مجموعات البيانات الخاصة بي ، فإن بعض المتغيرات التي تنتهي بـ ".A" وغيرها من المتغيرات تنتهي بـ ".B" وتريد فقط المتغيرات التي تنتهي بـ ".A" (على طول مع كل المتغيرات التي لا تتطابق مع أي من النسختين ، قم بهذا:
dfrm2 <- dfrm[ , -grep("\\.B$", names(dfrm)) ]
بالنسبة للحالة الحالية ، باستخدام مثال Joris Meys ، فقد لا يكون مضغوطًا ، لكنه سيكون:
DF <- DF[, -grep( paste("^",drops,"$", sep="", collapse="|"), names(DF) )]
إذا كنت تريد إزالة الأعمدة حسب المرجع وتجنب النسخ الداخلي المرتبط بـ data.frames
، فيمكنك استخدام الحزمة data.table
والوظيفة :=
يمكنك تمرير أسماء متجهات الأحرف إلى الجانب الأيسر من مشغل :=
، و NULL
كـ RHS.
library(data.table)
df <- data.frame(a=1:10, b=1:10, c=1:10, d=1:10)
DT <- data.table(df)
# or more simply DT <- data.table(a=1:10, b=1:10, c=1:10, d=1:10) #
DT[, c('a','b') := NULL]
إذا كنت ترغب في تحديد الأسماء كأحد خطوط الاتجاه خارج المكالمة إلى [
، فقم بلف اسم الكائن في ()
أو {}
لإجبار LHS على التقييم في نطاق الاستدعاء وليس كاسم ضمن نطاق DT
.
del <- c('a','b')
DT <- data.table(a=1:10, b=1:10, c=1:10, d=1:10)
DT[, (del) := NULL]
DT <- <- data.table(a=1:10, b=1:10, c=1:10, d=1:10)
DT[, {del} := NULL]
# force or `c` would also work.
يمكنك أيضًا استخدام set
، الذي يتجنب الحمل من [.data.table
، ويعمل أيضًا مع data.frames
!
df <- data.frame(a=1:10, b=1:10, c=1:10, d=1:10)
DT <- data.table(df)
# drop `a` from df (no copying involved)
set(df, j = 'a', value = NULL)
# drop `b` from DT (no copying involved)
set(DT, j = 'b', value = NULL)
إجابة dplyr
أخرى. إذا كانت المتغيرات الخاصة بك تحتوي على بنية تسمية شائعة ، فيمكنك تجربة starts_with()
. فمثلا
library(dplyr)
df <- data.frame(var1 = rnorm(5), var2 = rnorm(5), var3 = rnorm (5),
var4 = rnorm(5), char1 = rnorm(5), char2 = rnorm(5))
df
# var2 char1 var4 var3 char2 var1
#1 -0.4629512 -0.3595079 -0.04763169 0.6398194 0.70996579 0.75879754
#2 0.5489027 0.1572841 -1.65313658 -1.3228020 -1.42785427 0.31168919
#3 -0.1707694 -0.9036500 0.47583030 -0.6636173 0.02116066 0.03983268
df1 <- df %>% select(-starts_with("char"))
df1
# var2 var4 var3 var1
#1 -0.4629512 -0.04763169 0.6398194 0.75879754
#2 0.5489027 -1.65313658 -1.3228020 0.31168919
#3 -0.1707694 0.47583030 -0.6636173 0.03983268
إذا كنت تريد إسقاط سلسلة من المتغيرات في إطار البيانات ، يمكنك استخدام :
. على سبيل المثال ، إذا أردت إسقاط var2
و var3
و all المتغيرات بينهما ، فستترك فقط مع var1
:
df2 <- df1 %>% select(-c(var2:var3) )
df2
# var1
#1 0.75879754
#2 0.31168919
#3 0.03983268
بدافع الاهتمام ، يؤدي هذا إلى تمييز أحد أوجه التضارب في بناء جملة R العديدة الغريبة. على سبيل المثال إعطاء إطار بيانات عمودين:
df <- data.frame(x=1, y=2)
هذا يعطي إطار البيانات
subset(df, select=-y)
ولكن هذا يعطي ناقل
df[,-2]
تم توضيح كل ذلك في ?[
ولكنه ليس سلوكًا متوقعًا تمامًا. حسنا على الأقل ليس لي ...
DF <- data.frame(
x=1:10,
y=10:1,
z=rep(5,10),
a=11:20
)
DF
انتاج:
x y z a
1 1 10 5 11
2 2 9 5 12
3 3 8 5 13
4 4 7 5 14
5 5 6 5 15
6 6 5 5 16
7 7 4 5 17
8 8 3 5 18
9 9 2 5 19
10 10 1 5 20
DF[c("a","x")] <- list(NULL)
انتاج:
y z
1 10 5
2 9 5
3 8 5
4 7 5
5 6 5
6 5 5
7 4 5
8 3 5
9 2 5
10 1 5
امكانية اخرى:
df <- df[, setdiff(names(df), c("a", "c"))]
أو
df <- df[, grep('^(a|c)$', names(df), invert=TRUE)]
فيما يلي طريقة dplyr
للتعرف عليها:
#df[ -c(1,3:6, 12) ] # original
df.cut <- df %>% select(-col.to.drop.1, -col.to.drop.2, ..., -col.to.drop.6) # with dplyr::select()
يعجبني هذا لأنه سهل القراءة والفهم بدون تعليق توضيحي وقوي لتغيير الأعمدة موضعه داخل إطار البيانات. كما يتبع المصطلح المتجه باستخدام -
لإزالة العناصر.
حل Dplyr
أشك في أن هذا سيحصل على الكثير من الاهتمام هنا ، ولكن إذا كان لديك قائمة بالأعمدة التي تريد إزالتها ، وتريد القيام بذلك في سلسلة dplyr
، أستخدم one_of()
في جملة select
:
هنا مثال بسيط وقابل للتكرار:
undesired <- c('mpg', 'cyl', 'hp')
mtcars <- mtcars %>%
select(-one_of(undesired))
يمكن العثور على الوثائق عن طريق تشغيل ?one_of
أو هنا:
http://genomicsclass.github.io/book/pages/dplyr_tutorial.html
ما زلت أفكر في أنه يجب أن يكون هناك تعبير أفضل ، ولكن بالنسبة لطرح الأعمدة بالاسم ، فإنني أميل إلى القيام بما يلي:
df <- data.frame(a=1:10, b=1:10, c=1:10, d=1:10)
# return everything except a and c
df <- df[,-match(c("a","c"),names(df))]
df
هناك وظيفة تسمى dropNamed()
في حزمة BBmisc
الخاصة بـ Bernd Bischl والتي تقوم بذلك بالضبط.
BBmisc::dropNamed(df, "x")
الميزة هي أنه يتجنب تكرار وسيطة إطار البيانات ، وبالتالي فهو مناسب للأنابيب في magrittr
(تمامًا مثل نهج dplyr
):
df %>% BBmisc::dropNamed("x")
حل آخر إذا كنت لا تريد استخدام @ hadley أعلاه: إذا كان "COLUMN_NAME" هو اسم العمود الذي تريد إسقاطه:
df[,-which(names(df) == "COLUMN_NAME")]
خارج select(-one_of(drop_col_names))
الموضحة في الإجابات السابقة ، هناك خياران dplyr
آخران لإسقاط الأعمدة باستخدام select()
والتي لا تتضمن تحديد جميع أسماء الأعمدة المحددة (باستخدام بيانات نموذج نجوم النجوم dplyr لبعض أنواع أسماء الأعمدة):
library(dplyr)
starwars %>%
select(-(name:mass)) %>% # the range of columns from 'name' to 'mass'
select(-contains('color')) %>% # any column name that contains 'color'
select(-starts_with('bi')) %>% # any column name that starts with 'bi'
select(-ends_with('er')) %>% # any column name that ends with 'er'
select(-matches('^f.+s$')) %>% # any column name matching the regex pattern
select_if(~!is.list(.)) %>% # not by column name but by data type
head(2)
# A tibble: 2 x 2
homeworld species
<chr> <chr>
1 Tatooine Human
2 Tatooine Droid
ابحث عن فهرس الأعمدة التي تريد إسقاطها باستخدام which
. أعط هذه الفهارس علامة سلبية (*-1
). ثم مجموعة فرعية على تلك القيم ، والتي سوف إزالتها من قاعدة البيانات. هذا مثال.
DF <- data.frame(one=c('a','b'), two=c('c', 'd'), three=c('e', 'f'), four=c('g', 'h'))
DF
# one two three four
#1 a d f i
#2 b e g j
DF[which(names(DF) %in% c('two','three')) *-1]
# one four
#1 a g
#2 b h