मान लें कि आप एक मैट्रिक्स को एक सूची में बदलना चाहते हैं, जहां सूची के प्रत्येक तत्व में एक कॉलम होता है। list() या as.list() स्पष्ट रूप से काम नहीं करेगा, और अब तक मैं tapply के व्यवहार का उपयोग करके हैक का उपयोग करता हूं:

x <- matrix(1:10,ncol=2)

tapply(x,rep(1:ncol(x),each=nrow(x)),function(i)i)

मैं इससे पूरी तरह खुश नहीं हूं। कोई भी एक क्लीनर विधि जानता है जिसे मैं देख रहा हूं?

(पंक्तियों से भरी सूची बनाने के लिए, कोड को स्पष्ट रूप से बदला जा सकता है:

tapply(x,rep(1:nrow(x),ncol(x)),function(i)i)

)

88
Joris Meys 25 जुलाई 2011, 21:08
1
मुझे आश्चर्य है कि अनुकूलित आरसीसीपी समाधान तेज हो सकता है।
 – 
Marek
27 जुलाई 2011, 14:08
R 3.6 के वर्षों पहले जारी होने के साथ, यह उत्तर (asplit का उपयोग करके) स्वीकृत होना चाहिए।
 – 
jan-glx
30 जून 2021, 22:02

13 जवाब

सबसे बढ़िया उत्तर

बिल्ली की खाल उतारने के हित में, सरणी को एक वेक्टर के रूप में मानें जैसे कि उसमें कोई मंद विशेषता नहीं थी:

 split(x, rep(1:ncol(x), each = nrow(x)))
73
mdsumner 26 जुलाई 2011, 03:17
9
यह tapply क्या करता है इसका मूल है। लेकिन यह आसान है :)। शायद धीमा लेकिन अच्छा दिखने वाला समाधान split(x, col(x)) (और split(x, row(x)) क्रमशः) होगा।
 – 
Marek
27 जुलाई 2011, 12:49
मैंने इसे जाँचा था। उतना ही तेज़ split(x, c(col(x))) होगा। लेकिन यह बदतर दिखता है।
 – 
Marek
27 जुलाई 2011, 13:16
2
Split(x, col(x)) बेहतर दिखता है - वेक्टर के लिए निहित जबरदस्ती ठीक है। . .
 – 
mdsumner
28 जुलाई 2011, 03:07
2
बहुत परीक्षण के बाद, ऐसा लगता है कि यह सबसे तेज़ काम करता है, खासकर बहुत सी पंक्तियों या स्तंभों के साथ।
 – 
Joris Meys
2 मार्च 2012, 18:24
2
ध्यान दें कि यदि x के कॉलम नाम हैं तो split(x, col(x, as.factor = TRUE)) नामों को सुरक्षित रखेंगे।
 – 
banbh
20 अगस्त 2018, 18:48

गेविन का उत्तर सरल और सुरुचिपूर्ण है। लेकिन अगर कई कॉलम हैं, तो बहुत तेज़ समाधान होगा:

lapply(seq_len(ncol(x)), function(i) x[,i])

नीचे दिए गए उदाहरण में गति अंतर 6x है:

> x <- matrix(1:1e6, 10)
> system.time( as.list(data.frame(x)) )
   user  system elapsed 
   1.24    0.00    1.22 
> system.time( lapply(seq_len(ncol(x)), function(i) x[,i]) )
   user  system elapsed 
    0.2     0.0     0.2 
81
Tommy 25 जुलाई 2011, 23:41
2
+1 विभिन्न समाधानों की सापेक्ष दक्षता के बारे में अच्छी बात। अब तक का सबसे अच्छा जवाब।
 – 
Gavin Simpson
30 जुलाई 2011, 12:57
लेकिन मुझे लगता है कि समान परिणाम प्राप्त करने के लिए आपको lapply(seq_len(nrow(x)), function(i) x[i,]) करने की आवश्यकता है और फिर धीमा है।
 – 
skan
2 नवम्बर 2019, 00:15

Data.frames सूचियों के रूप में संग्रहीत हैं, मुझे विश्वास है। इसलिए जबरदस्ती सबसे अच्छी लगती है:

as.list(as.data.frame(x))
> as.list(as.data.frame(x))
$V1
[1] 1 2 3 4 5

$V2
[1]  6  7  8  9 10

बेंचमार्किंग परिणाम दिलचस्प हैं। as.data.frame data.frame से तेज़ है, या तो क्योंकि data.frame को एक पूरी नई वस्तु बनाना है, या क्योंकि कॉलम नामों का ट्रैक रखना किसी भी तरह महंगा है (गवाह सी (अनाम ()) बनाम सी () तुलना )? @Tommy द्वारा प्रदान किया गया लैपली समाधान परिमाण के क्रम से तेज़ है। मैन्युअल रूप से जबरदस्ती करके as.data.frame() परिणामों को कुछ हद तक सुधारा जा सकता है।

manual.coerce <- function(x) {
  x <- as.data.frame(x)
  class(x) <- "list"
  x
}

library(microbenchmark)
x <- matrix(1:10,ncol=2)

microbenchmark(
  tapply(x,rep(1:ncol(x),each=nrow(x)),function(i)i) ,
  as.list(data.frame(x)),
  as.list(as.data.frame(x)),
  lapply(seq_len(ncol(x)), function(i) x[,i]),
  c(unname(as.data.frame(x))),
  c(data.frame(x)),
  manual.coerce(x),
  times=1000
  )

                                                      expr     min      lq
1                                as.list(as.data.frame(x))  176221  183064
2                                   as.list(data.frame(x))  444827  454237
3                                         c(data.frame(x))  434562  443117
4                              c(unname(as.data.frame(x)))  257487  266897
5             lapply(seq_len(ncol(x)), function(i) x[, i])   28231   35929
6                                         manual.coerce(x)  160823  167667
7 tapply(x, rep(1:ncol(x), each = nrow(x)), function(i) i) 1020536 1036790
   median      uq     max
1  186486  190763 2768193
2  460225  471346 2854592
3  449960  460226 2895653
4  271174  277162 2827218
5   36784   37640 1165105
6  171088  176221  457659
7 1052188 1080417 3939286

is.list(manual.coerce(x))
[1] TRUE
27
Ari B. Friedman 27 जुलाई 2011, 12:57
गेविन ने 5 सेकंड से हराया। डर्न यू, "आर यू आर ह्यूमन" स्क्रीन? :-)
 – 
Ari B. Friedman
25 जुलाई 2011, 21:19
1
मुझे लगता है कि ड्रॉ की किस्मत, मैं इसे देख रहा था जब @Joris ने मेरे आगे पेर्टर फ्लॉम के प्रश्न का उत्तर दिया। इसके अलावा, as.data.frame() डेटा फ्रेम के नाम खो देता है, इसलिए data.frame() थोड़ा अच्छा है .
 – 
Gavin Simpson
25 जुलाई 2011, 21:21
2
manual.coerce(x) के बराबर unclass(as.data.frame(x)) हो सकता है।
 – 
Marek
27 जुलाई 2011, 12:52
धन्यवाद मारेक। यह लगभग 6% तेज है, संभवतः क्योंकि मैं फ़ंक्शन परिभाषा/कॉल का उपयोग करने से बच सकता हूं।
 – 
Ari B. Friedman
27 जुलाई 2011, 12:57

एक डेटा फ्रेम में कनवर्ट करना तब से एक सूची में काम करता प्रतीत होता है:

> as.list(data.frame(x))
$X1
[1] 1 2 3 4 5

$X2
[1]  6  7  8  9 10
> str(as.list(data.frame(x)))
List of 2
 $ X1: int [1:5] 1 2 3 4 5
 $ X2: int [1:5] 6 7 8 9 10
16
Gavin Simpson 25 जुलाई 2011, 21:18

इस तरह की चीजों के लिए plyr का उपयोग करना वास्तव में उपयोगी हो सकता है:

library("plyr")

alply(x,2)

$`1`
[1] 1 2 3 4 5

$`2`
[1]  6  7  8  9 10

attr(,"class")
[1] "split" "list" 
13
Sacha Epskamp 27 जुलाई 2011, 11:48

मैट्रिक्स को वैक्टर की सूची में बदलने के लिए asplit का उपयोग करें

asplit(x, 1) # split into list of row vectors
asplit(x, 2) # split into list of column vectors
8
Daniel Freeman 5 फरवरी 2020, 17:47

मुझे पता है कि यह आर में अभिशाप है, और मेरे पास इसे वापस करने के लिए वास्तव में बहुत प्रतिष्ठा नहीं है, लेकिन मुझे लूप के लिए और अधिक कुशल होने के लिए मिल रहा है। मैं मैट्रिक्स मैट को इसके कॉलम की सूची में बदलने के लिए निम्न फ़ंक्शन का उपयोग कर रहा हूं:

mat2list <- function(mat)
{
    list_length <- ncol(mat)
    out_list <- vector("list", list_length)
    for(i in 1:list_length) out_list[[i]] <- mat[,i]
    out_list
}

Mdsummer और मूल समाधान के साथ तुलना करने वाला त्वरित बेंचमार्क:

x <- matrix(1:1e7, ncol=1e6)

system.time(mat2list(x))
   user  system elapsed 
  2.728   0.023   2.720 

system.time(split(x, rep(1:ncol(x), each = nrow(x))))
   user  system elapsed 
  4.812   0.194   4.978 

system.time(tapply(x,rep(1:ncol(x),each=nrow(x)),function(i)i))
   user  system elapsed 
 11.471   0.413  11.817 
6
alfymbohm 2 अगस्त 2013, 16:30
बेशक यह कॉलम नाम छोड़ देता है, लेकिन ऐसा नहीं लगता कि वे मूल प्रश्न में महत्वपूर्ण थे।
 – 
alfymbohm
2 अगस्त 2013, 15:39
2
टॉमी का समाधान तेज़ और अधिक कॉम्पैक्ट है: system.time( lapply(seq_len(ncol(x)), function(i) x[,i]) ) user: 1.668 system: 0.016 elapsed: 1.693
 – 
alfymbohm
4 अगस्त 2013, 12:46
इसे एक अलग संदर्भ में समझने की कोशिश करना, काम नहीं करता है: stackoverflow.com/questions/63801018.... ढूंढ रहे हैं यह: vec2 = castMatrixToSequenceOfLists(vecs);
 – 
mshaffer
8 सितंबर 2020, 23:45

नया फ़ंक्शन asplit() v3.6 में आधार R पर आ जाएगा। तब तक और @mdsumner के उत्तर के समान भाव से हम भी कर सकते हैं

split(x, slice.index(x, MARGIN))

asplit() के दस्तावेज़ों के अनुसार। जैसा कि पहले दिखाया गया था, सभी split() आधारित समाधान @ टॉमी के lapply/`[` की तुलना में बहुत धीमे हैं। यह नए asplit() के लिए भी है, कम से कम अपने वर्तमान स्वरूप में।

split_1 <- function(x) asplit(x, 2L)
split_2 <- function(x) split(x, rep(seq_len(ncol(x)), each = nrow(x)))
split_3 <- function(x) split(x, col(x))
split_4 <- function(x) split(x, slice.index(x, 2L))
split_5 <- function(x) lapply(seq_len(ncol(x)), function(i) x[, i])

dat <- matrix(rnorm(n = 1e6), ncol = 100)

#> Unit: milliseconds
#>          expr       min        lq     mean   median        uq        max neval
#>  split_1(dat) 16.250842 17.271092 20.26428 18.18286 20.185513  55.851237   100
#>  split_2(dat) 52.975819 54.600901 60.94911 56.05520 60.249629 105.791117   100
#>  split_3(dat) 32.793112 33.665121 40.98491 34.97580 39.409883  74.406772   100
#>  split_4(dat) 37.998140 39.669480 46.85295 40.82559 45.342010  80.830705   100
#>  split_5(dat)  2.622944  2.841834  3.47998  2.88914  4.422262   8.286883   100

dat <- matrix(rnorm(n = 1e6), ncol = 1e5)

#> Unit: milliseconds
#>          expr       min       lq     mean   median       uq      max neval
#>  split_1(dat) 204.69803 231.3023 261.6907 246.4927 289.5218 413.5386   100
#>  split_2(dat) 229.38132 235.3153 253.3027 242.0433 259.2280 339.0016   100
#>  split_3(dat) 208.29162 216.5506 234.2354 221.7152 235.3539 342.5918   100
#>  split_4(dat) 214.43064 221.9247 240.7921 231.0895 246.2457 323.3709   100
#>  split_5(dat)  89.83764 105.8272 127.1187 114.3563 143.8771 209.0670   100
6
nbenn 1 फरवरी 2019, 19:15

के अंतर्गत कुछ R सहायता साइट तक पहुँचा जा सकता है nabble.com मैं पाता हूं:

c(unname(as.data.frame(x))) 

एक वैध समाधान के रूप में और मेरे आर v2.13.0 में यह ठीक दिखता है:

> y <- c(unname(as.data.frame(x)))
> y
[[1]]
[1] 1 2 3 4 5

[[2]]
[1]  6  7  8  9 10

प्रदर्शन तुलना या यह कितना साफ है, इसके बारे में कुछ भी नहीं कह सकता ;-)

2
Dilettant 25 जुलाई 2011, 21:18
2
दिलचस्प। मुझे लगता है कि यह भी जबरदस्ती से काम करता है। c(as.data.frame(x)), as.list(as.data.frame(x) के समान व्यवहार उत्पन्न करता है
 – 
Ari B. Friedman
25 जुलाई 2011, 21:20
मुझे लगता है कि ऐसा इसलिए है, क्योंकि नमूना सूचियों/मैट्रिक्स के सदस्य एक ही प्रकार के हैं, लेकिन मैं एक विशेषज्ञ नहीं हूं।
 – 
Dilettant
25 जुलाई 2011, 21:29

आप apply और फिर c का उपयोग do.call के साथ कर सकते हैं

x <- matrix(1:10,ncol=2)
do.call(c, apply(x, 2, list))
#[[1]]
#[1] 1 2 3 4 5
#
#[[2]]
#[1]  6  7  8  9 10

और ऐसा लगता है कि मैट्रिक्स में जोड़े जाने पर यह कॉलम नामों को सुरक्षित रखेगा।

colnames(x) <- c("a", "b")
do.call(c, apply(x, 2, list))
#$a
#[1] 1 2 3 4 5
#
#$b
#[1]  6  7  8  9 10
2
Rich Scriven 1 सितंबर 2014, 11:59
5
या unlist(apply(x, 2, list), recursive = FALSE)
 – 
baptiste
1 सितंबर 2014, 03:21
हां। आपको इसे @baptiste के उत्तर के रूप में जोड़ना चाहिए।
 – 
Rich Scriven
1 सितंबर 2014, 03:23
1
लेकिन इसके लिए पृष्ठ के नीचे स्क्रॉल करने की आवश्यकता होगी! मैं उसके लिए बहुत आलसी हूँ
 – 
baptiste
1 सितंबर 2014, 03:40
मेरी मशीन पर एक "END" बटन है... :-)
 – 
Rich Scriven
1 सितंबर 2014, 03:42
मुझे लगता है कि यह शायद एक खाली सूची बनाकर और उसे भरकर भी किया जा सकता है। y <- vector("list", ncol(x)) और फिर y[1:2] <- x[,1:2] की तर्ज पर कुछ, हालांकि यह ठीक उसी तरह काम नहीं करता है।
 – 
Rich Scriven
1 सितंबर 2014, 03:43

ConvertRowsToList {BBmisc}

डेटा.फ्रेम या मैट्रिक्स की पंक्तियों (कॉलम) को सूचियों में बदलें।

BBmisc::convertColsToList(x)

रेफरी: http://berndbischl.github.io/BBmisc/man/convertRowsToList.html< /ए>

2
Zhilong Jia 23 फरवरी 2018, 06:24

मामूली मामले में जहां कॉलम की संख्या छोटी और स्थिर है, तो मैंने पाया है कि सबसे तेज़ विकल्प रूपांतरण को हार्ड-कोड करना है:

mat2list  <- function (mat) lapply(1:2, function (i) mat[, i])
mat2list2 <- function (mat) list(mat[, 1], mat[, 2])


## Microbenchmark results; unit: microseconds
#          expr   min    lq    mean median    uq    max neval
##  mat2list(x) 7.464 7.932 8.77091  8.398 8.864 29.390   100
## mat2list2(x) 1.400 1.867 2.48702  2.333 2.333 27.525   100
1
ms609 6 नवम्बर 2017, 20:27

एक सूची बनाने का सबसे आसान तरीका जिसमें मैट्रिक्स मैट के कॉलम इसके तत्वों के रूप में हैं, इस तथ्य का उपयोग करना है कि आर में डेटा.फ्रेम ऑब्जेक्ट आंतरिक रूप से कॉलम की सूची के रूप में दर्शाया जाता है। इस प्रकार केवल निम्नलिखित पंक्ति की आवश्यकता है

mat.list <- as.data.frame(mat)
0
Nick Hengartner 13 मई 2021, 01:53