Soru Veri çerçevesinin satırlarını birleştirin


Karakterler ve sayılar içeren bir veri karesi almak ve her satırın tüm öğelerini bir vektörde tek bir öğe olarak saklanacak tek bir dizeye birleştirmek istiyorum. Örnek olarak, harf ve sayıların bir veri çerçevesini hazırlıyorum ve sonra ilk satırı yapıştır işleviyle birleştirmek istiyorum ve umarım "A1" değerini döndürürüm.

df <- data.frame(letters = LETTERS[1:5], numbers = 1:5)
df

##   letters numbers
## 1       A       1
## 2       B       2
## 3       C       3
## 4       D       4
## 5       E       5

paste(df[1,], sep =".")
## [1] "1" "1"

Yapıştır, satırın her bir elemanını, bir faktör gibi 'karşılık gelen seviyenin indeksine' karşılık gelen bir tamsayıya dönüştürür ve onu, iki uzunluğun bir vektörü olarak tutar. (Karakterlere zorlanan faktörlerin bu şekilde davrandığını / inandığını, ancak R'nin bir faktör olarak df [1] değerini kaydetmediğini (is.factor () tarafından test edildiğini) biliyorum. aslında bir seviye için bir endeks)

is.factor(df[1,])
## [1] FALSE
is.vector(df[1,])
## [1] FALSE

Öyleyse eğer bir vektör değilse o zaman garip davranıyor, ama onu bir vektöre zorlayamam.

> is.vector(as.vector(df[1,]))
[1] FALSE

kullanma as.character benim girişimlerimde yardımcı olmadı

Bu davranışı herkes açıklayabilir mi?


25
2017-12-19 01:07


Menşei


Eklemeyi denediniz mi stringsAsFactors=FALSE data.frame oluşturmanıza yönelik argüman? - sebastian-c


Cevaplar:


Diğerleri, kodunuzun neden çalışmadığına ve nasıl geliştirileceğine odaklanmış olsa da, istediğiniz sonucu elde etmeye daha çok odaklanmaya çalışacağım. Açıklamanızdan, yapıştırmayı kullanarak istediğinizi kolayca elde edebileceğiniz gibi görünüyor:

df <- data.frame(letters = LETTERS[1:5], numbers = 1:5, stringsAsFactors=FALSE)
paste(df$letters, df$numbers, sep=""))

## [1] "A1" "B2" "C3" "D4" "E5"

Değiştirebilirsin df$letters karakter kullanarak df$letters <- as.character(df$letters) eğer kullanmak istemiyorsan stringsAsFactors argüman.

Ama düşün ki, istediğin bu değil. Yüzlerce sütununuz olduğunu ve hepsini bir arada yapıştırmak istediğinizi varsayalım. Bunu en küçük örneğinizle de yapabiliriz:

df_args <- c(df, sep="")
do.call(paste, df_args)

## [1] "A1" "B2" "C3" "D4" "E5"

EDIT: Alternatif yöntem ve açıklama:

Yaşadığınız sorunu, bir faktörü kullandığınız ve kullanmanızın bir bileşimi olduğunu anladım. sep yerine argüman collapse (@adibender alındı). Fark şu ki sep ayırıcıyı iki ayrı vektör arasında verir ve collapse Bir vektör içinde ayırıcılar verir. Kullandığında df[1,], sen tek bir vektör kaynağı paste ve dolayısıyla kullanmalısınız collapse argüman. Her sırayı alma ve onları birleştirme fikrinizi kullanarak, aşağıdaki kod satırı tam olarak ne istediğinizi yapacağız:

apply(df, 1, paste, collapse="")

Tamam, şimdi açıklamaları için:

Neden olmasın as.list iş?

as.list bir nesneyi bir listeye dönüştürür. Yani işe yarıyor. Dataframe'inizi bir listeye dönüştürecek ve daha sonra bunu görmezden gelecektir. sep="" argüman. c nesneleri birleştirir. Teknik olarak, bir veri çerçevesi, her sütunun bir eleman olduğu ve tüm öğelerin aynı uzunlukta olması gereken bir listedir. Yani ben ile birleştirdiğimde sep=""Dataframe'in sütunlarıyla elementler olarak düzenli bir liste haline gelir.

Neden kullanmak do.call?

do.call argümanlar olarak adlandırılmış bir liste kullanarak bir işlevi çağırmak için izin verir. Listeyi doğruca atamazsın. pasteçünkü dataframları sevmiyor. Vektörleri birleştirmek için tasarlanmıştır. Bunu hatırla dfargs bir vektörü içeren bir listedir, sadece "" içeren bir uzunluk 1 vektörü olan sayı ve sep vektörüdür. Kullandigimda do.callSonuçta elde edilen yapıştırma işlevi esas olarak paste(letters, numbers, sep).
Ama orijinal veri çerçevemde sütunlar varsa "letters", "numbers", "squigs", "blargs" Bundan sonra ayırıcıyı daha önce yaptığım gibi ekledim? Daha sonra yapıştırmak işlevi do.call Benzeyecekmiş gibi:

paste(letters, numbers, squigs, blargs, sep)

Yani görüyorsunuz, herhangi bir sayıda sütun için çalışır.


47
2017-12-19 01:32



Teşekkür ederim, bu bir atasözü cazibe gibi çalışır. 'C' operatörü aracılığıyla bir listeye dönüştürme neden as.list () kullanarak farklıdır ve neden macun () kullanarak yerine macun aramak için do.call () kullandığınız hakkında ayrıntılı bilgi verebilir misiniz? Açıkçası bu seçenekler işe yaramıyor, ama sezgisel olarak olması gerektiği gibi görünüyor - Sam
Teşekkürler sebastian-c! 'Apply' ile çıldırıyordum çünkü sep = "" yerine collapse = "" kullanıyordum. - Davit Sargsyan


Bu gerçekten biraz tuhaf ama aynı zamanda olması gereken de bu. Oluşturduğunuzda data.frame yaptığın gibi, sütun letters olarak depolanır factor. Doğal olarak faktörler sipariş vermez, as.numeric() Faktöre uygulandığında faktörü sipariş eder. Örneğin:

> df[, 1]
[1] A B C D E
Levels: A B C D E
> as.numeric(df[, 1])
[1] 1 2 3 4 5

A faktörün ilk seviyesi df[, 1] bu nedenle A değere dönüştürülür 1, ne zaman as.numeric uygulanır. Aradığınızda ne oluyor bu paste(df[1, ]). 1. ve 2. sütunlar farklı sınıf olduğundan, yapıştırma ilk önce satır 1'in her iki öğeyi de sayısal olarak sonra karakterlere dönüştürür.

Her iki sütunu da birleştirmek istediğinizde, önce ilk satırı karaktere dönüştürmeniz gerekir:

df[, 1] <- as.character(df[, 1])
paste(df[1,], collapse = "")

@ Sebastian-c belirtildiği gibi, ayrıca kullanabilirsiniz stringsAsFactors = FALSE data.frame'in oluşturulmasında, o zaman as.character() adım.


3
2017-12-19 01:28





Kütüphaneyi kullananlar için (tidyverse), birleştirme işlevini kullanabilirsiniz.

 new.df<-df%>%
 unite(together, letters, numbers, sep="")

Bu size A1, B2, vb. İle birlikte "birlikte" adlı yeni bir sütun verecektir.


3
2018-05-11 19:04



Muhtemelen gerçek paketi tanımlamak için daha iyi fonksiyon geliyor (tidyr?). - Frank
Tidyverse paketi - Shirley
Tidyverse bir paket paketidir. Deneyin ?tidyverse::unite -- Orada hiçbir şey yok. Sadece kullanmak istediğiniz sorunu çözmek ve tüm paketi yüklemek istemeyen millet için, onlar sadece tidyr yükleyebilirsiniz bilmek güzel olurdu. Btw, cevapladığım eleştiriyi eleştirmiyorum, sadece bir gelişme önermek. - Frank
Açıklama için teşekkürler, çok takdir edilmektedir. Evet, birleşme işlevi aslında işaret ettiğin gibi tidyr paketine ait. - Shirley
birleştirmek satırları değil, sütunları birleştirir. - jzadra


eğer başlamak istersen

df <- data.frame(letters = LETTERS[1:5], numbers = 1:5, stringsAsFactors=TRUE)

.. o zaman nasıl olduğu hakkında genel bir kural yoktur. df$letters herhangi bir işlev tarafından yorumlanacaktır. Bazıları için bazı ve tamsayı için karakter modelleme, karakter için bir faktördür. Macun gibi aynı işlev, onu nasıl kullandığınıza bağlı olarak farklı şekilde yorumlayabilir:

paste(df[1,], collapse="") # "11"
apply(df, 1, paste, collapse="") # "A1" "B2" "C3" "D4" "E5"

İçinde herhangi bir mantık yoktur, ancak her işlevin içsellerini bildiğiniz zaman muhtemelen mantıklı olacaktır.

Bir argüman vektöre dönüştürüldüğünde, faktörler tamsayıya dönüştürülür gibi görünmektedir (bildiğiniz gibi, veri çerçeveleri eşit uzunluktaki vektörlerin listeleridir, bu yüzden bir veri çerçevesinin ilk satırı aynı zamanda bir listedir. bir vektör, böyle bir şey olur :)

df[1,]
#    letters numbers
# 1       A       1
unlist(df[1,])
# letters numbers 
#  1       1 

Nasıl bilmiyorum apply ne yaptığını (yani, faktörler karakter değerleri ile temsil edilir) başarır - eğer ilgileniyorsanız, kaynak koduna bakın. Yine de, bu özgüven içinde güvenebileceğinizi bilmek faydalı olabilir. apply (bu belirli durumlarda). Daha genel olarak, her bir veri parçasını hassas bir biçimde saklamak yararlıdır, bu da dizeleri diziler olarak depolamayı içerir, yani stringsAsFactors=FALSE.

Btw, her tanıtıcı R kitabının bu fikri bir alt başlıkta içermesi gerekir. Örneğin, emeklilik planım "R ile veri balıkçılığına A (çok da değil) nazikçe giriş", dizeleriAsFactors = FALSE yolu "yazmaktır.


0
2018-01-19 09:36