열의 텍스트를 여러 행으로 분할하는 방법
큰 csv 파일로 작업 중이고 마지막 열 옆에 특정 구분 기호로 분할할 텍스트 문자열이 있습니다.판다나 비단뱀을 이용해서 간단하게 할 수 있는 방법이 있을까요?
CustNum CustomerName ItemQty Item Seatblocks ItemExt
32363 McCartney, Paul 3 F04 2:218:10:4,6 60
31316 Lennon, John 25 F01 1:13:36:1,12 1:13:37:1,13 300
나는 공간으로 나누고 싶습니다.(' ')
그리고 결장은(':')
에서Seatblocks
열, 그러나 각 셀의 열 수는 다릅니다.저는 열을 다시 정렬하는 기능을 가지고 있습니다.Seatblocks
열은 시트의 끝에 있지만, 거기서 무엇을 해야 할지 모르겠습니다.내장된 기능으로 탁월하게 수행할 수 있습니다.text-to-columns
기능과 빠른 매크로가 있지만 내 데이터 세트에 레코드가 너무 많아서 엑셀로 처리할 수 없습니다.
궁극적으로, 저는 존 레논의 레코드를 가져와서 각 좌석 세트의 정보를 별도의 줄에 두고 여러 줄을 만들고 싶습니다.
이렇게 하면 시트 블록이 공간별로 분할되고 각각의 행이 제공됩니다.
In [43]: df
Out[43]:
CustNum CustomerName ItemQty Item Seatblocks ItemExt
0 32363 McCartney, Paul 3 F04 2:218:10:4,6 60
1 31316 Lennon, John 25 F01 1:13:36:1,12 1:13:37:1,13 300
In [44]: s = df['Seatblocks'].str.split(' ').apply(Series, 1).stack()
In [45]: s.index = s.index.droplevel(-1) # to line up with df's index
In [46]: s.name = 'Seatblocks' # needs a name to join
In [47]: s
Out[47]:
0 2:218:10:4,6
1 1:13:36:1,12
1 1:13:37:1,13
Name: Seatblocks, dtype: object
In [48]: del df['Seatblocks']
In [49]: df.join(s)
Out[49]:
CustNum CustomerName ItemQty Item ItemExt Seatblocks
0 32363 McCartney, Paul 3 F04 60 2:218:10:4,6
1 31316 Lennon, John 25 F01 300 1:13:36:1,12
1 31316 Lennon, John 25 F01 300 1:13:37:1,13
또는 콜론으로 구분된 각 문자열을 자체 열에 지정하려면 다음을 수행합니다.
In [50]: df.join(s.apply(lambda x: Series(x.split(':'))))
Out[50]:
CustNum CustomerName ItemQty Item ItemExt 0 1 2 3
0 32363 McCartney, Paul 3 F04 60 2 218 10 4,6
1 31316 Lennon, John 25 F01 300 1 13 36 1,12
1 31316 Lennon, John 25 F01 300 1 13 37 1,13
이것은 조금 추악하지만, 아마도 누군가가 더 예쁜 해결책을 제안할 것입니다.
댄과는 달리, 그의 대답은 매우 우아하다고 생각합니다...하지만 불행하게도 그것은 매우 비효율적입니다.따라서 질문에 "대규모 csv 파일"이 언급되었으므로 셸 Dan의 솔루션을 사용해 볼 것을 제안합니다.
time python -c "import pandas as pd;
df = pd.DataFrame(['a b c']*100000, columns=['col']);
print df['col'].apply(lambda x : pd.Series(x.split(' '))).head()"
이 대안과 비교하면:
time python -c "import pandas as pd;
from scipy import array, concatenate;
df = pd.DataFrame(['a b c']*100000, columns=['col']);
print pd.DataFrame(concatenate(df['col'].apply( lambda x : [x.split(' ')]))).head()"
그리고 이것은:
time python -c "import pandas as pd;
df = pd.DataFrame(['a b c']*100000, columns=['col']);
print pd.DataFrame(dict(zip(range(3), [df['col'].apply(lambda x : x.split(' ')[i]) for i in range(3)]))).head()"
두 번째는 단순히 100,000 시리즈를 할당하는 것을 자제하며, 이는 약 10배의 속도를 내기에 충분합니다.그러나 str.split()에 대한 호출을 다소 많이 낭비하는 세 번째 솔루션(행당 열에 한 번씩 호출되므로 다른 두 솔루션보다 세 배 더 많이 호출됨)은 100,000개의 목록을 인스턴스화하는 것조차 피하므로 첫 번째 솔루션보다 약 40배 더 빠릅니다.그리고 네, 확실히 조금 못생겼습니다...
편집: 이 답변은 "to_list()"를 사용하고 람다가 필요하지 않도록 하는 방법을 제안합니다.결과는 다음과 같습니다.
time python -c "import pandas as pd;
df = pd.DataFrame(['a b c']*100000, columns=['col']);
print pd.DataFrame(df.col.str.split().tolist()).head()"
세 번째 솔루션보다 훨씬 더 효율적이고 훨씬 더 우아합니다.
편집: 훨씬 단순합니다.
time python -c "import pandas as pd;
df = pd.DataFrame(['a b c']*100000, columns=['col']);
print pd.DataFrame(list(df.col.str.split())).head()"
작동하기도 하고, 거의 그만큼 효율적입니다.
편집: 훨씬 더 간단합니다!그리고 NaNs를 처리합니다(그러나 효율성은 떨어짐).
time python -c "import pandas as pd;
df = pd.DataFrame(['a b c']*100000, columns=['col']);
print df.col.str.split(expand=True).head()"
import pandas as pd
import numpy as np
df = pd.DataFrame({'ItemQty': {0: 3, 1: 25},
'Seatblocks': {0: '2:218:10:4,6', 1: '1:13:36:1,12 1:13:37:1,13'},
'ItemExt': {0: 60, 1: 300},
'CustomerName': {0: 'McCartney, Paul', 1: 'Lennon, John'},
'CustNum': {0: 32363, 1: 31316},
'Item': {0: 'F04', 1: 'F01'}},
columns=['CustNum','CustomerName','ItemQty','Item','Seatblocks','ItemExt'])
print (df)
CustNum CustomerName ItemQty Item Seatblocks ItemExt
0 32363 McCartney, Paul 3 F04 2:218:10:4,6 60
1 31316 Lennon, John 25 F01 1:13:36:1,12 1:13:37:1,13 300
체인을 사용하는 또 다른 유사한 솔루션은 다음과 같습니다.
print (df.drop('Seatblocks', axis=1)
.join
(
df.Seatblocks
.str
.split(expand=True)
.stack()
.reset_index(drop=True, level=1)
.rename('Seatblocks')
))
CustNum CustomerName ItemQty Item ItemExt Seatblocks
0 32363 McCartney, Paul 3 F04 60 2:218:10:4,6
1 31316 Lennon, John 25 F01 300 1:13:36:1,12
1 31316 Lennon, John 25 F01 300 1:13:37:1,13
열에 NOT인 경우 NaN
values,은 가치, 가빠해결사은다니용을 사용하는 입니다.list
에대이에 대한 DataFrame
생성자:
df = pd.DataFrame(['a b c']*100000, columns=['col'])
In [141]: %timeit (pd.DataFrame(dict(zip(range(3), [df['col'].apply(lambda x : x.split(' ')[i]) for i in range(3)]))))
1 loop, best of 3: 211 ms per loop
In [142]: %timeit (pd.DataFrame(df.col.str.split().tolist()))
10 loops, best of 3: 87.8 ms per loop
In [143]: %timeit (pd.DataFrame(list(df.col.str.split())))
10 loops, best of 3: 86.1 ms per loop
In [144]: %timeit (df.col.str.split(expand=True))
10 loops, best of 3: 156 ms per loop
In [145]: %timeit (pd.DataFrame([ x.split() for x in df['col'].tolist()]))
10 loops, best of 3: 54.1 ms per loop
그러나 열에 다음이 포함된 경우NaN
매개 변수와 함께만 작동합니다.expand=True
어느 쪽이 돌아오는지DataFrame
(해석), 그리고 그것은 그것이 더 느린 이유를 설명합니다.
df = pd.DataFrame(['a b c']*10, columns=['col'])
df.loc[0] = np.nan
print (df.head())
col
0 NaN
1 a b c
2 a b c
3 a b c
4 a b c
print (df.col.str.split(expand=True))
0 1 2
0 NaN None None
1 a b c
2 a b c
3 a b c
4 a b c
5 a b c
6 a b c
7 a b c
8 a b c
9 a b c
저는 의 두 특징을 : 판다의 좋은 점을 기록하기를 바랍니다.pandas.Series.str.split()
과 규적인표그리고로으정칙▁regular그로.pandas.Series.explode()
.
import pandas as pd
import numpy as np
df = pd.DataFrame(
{'CustNum': [32363, 31316],
'CustomerName': ['McCartney, Paul', 'Lennon, John'],
'ItemQty': [3, 25],
'Item': ['F04', 'F01'],
'Seatblocks': ['2:218:10:4,6', '1:13:36:1,12 1:13:37:1,13'],
'ItemExt': [60, 360]
}
)
print(df)
print('-'*80+'\n')
df['Seatblocks'] = df['Seatblocks'].str.split('[ :]')
df = df.explode('Seatblocks').reset_index(drop=True)
cols = list(df.columns)
cols.append(cols.pop(cols.index('CustomerName')))
df = df[cols]
print(df)
print('='*80+'\n')
print(df[df['CustomerName'] == 'Lennon, John'])
출력은 다음과 같습니다.
CustNum CustomerName ItemQty Item Seatblocks ItemExt
0 32363 McCartney, Paul 3 F04 2:218:10:4,6 60
1 31316 Lennon, John 25 F01 1:13:36:1,12 1:13:37:1,13 360
--------------------------------------------------------------------------------
CustNum ItemQty Item Seatblocks ItemExt CustomerName
0 32363 3 F04 2 60 McCartney, Paul
1 32363 3 F04 218 60 McCartney, Paul
2 32363 3 F04 10 60 McCartney, Paul
3 32363 3 F04 4,6 60 McCartney, Paul
4 31316 25 F01 1 360 Lennon, John
5 31316 25 F01 13 360 Lennon, John
6 31316 25 F01 36 360 Lennon, John
7 31316 25 F01 1,12 360 Lennon, John
8 31316 25 F01 1 360 Lennon, John
9 31316 25 F01 13 360 Lennon, John
10 31316 25 F01 37 360 Lennon, John
11 31316 25 F01 1,13 360 Lennon, John
================================================================================
CustNum ItemQty Item Seatblocks ItemExt CustomerName
4 31316 25 F01 1 360 Lennon, John
5 31316 25 F01 13 360 Lennon, John
6 31316 25 F01 36 360 Lennon, John
7 31316 25 F01 1,12 360 Lennon, John
8 31316 25 F01 1 360 Lennon, John
9 31316 25 F01 13 360 Lennon, John
10 31316 25 F01 37 360 Lennon, John
11 31316 25 F01 1,13 360 Lennon, John
이 방법은 이 스레드의 다른 곳에서 제안된 방법보다 훨씬 쉬운 것 같습니다.
또 다른 접근 방식은 다음과 같습니다.
temp = df['Seatblocks'].str.split(' ')
data = data.reindex(data.index.repeat(temp.apply(len)))
data['new_Seatblocks'] = np.hstack(temp)
가입 및 스택() 없이 groupby()를 사용할 수도 있습니다.
위의 예제 데이터 사용:
import pandas as pd
import numpy as np
df = pd.DataFrame({'ItemQty': {0: 3, 1: 25},
'Seatblocks': {0: '2:218:10:4,6', 1: '1:13:36:1,12 1:13:37:1,13'},
'ItemExt': {0: 60, 1: 300},
'CustomerName': {0: 'McCartney, Paul', 1: 'Lennon, John'},
'CustNum': {0: 32363, 1: 31316},
'Item': {0: 'F04', 1: 'F01'}},
columns=['CustNum','CustomerName','ItemQty','Item','Seatblocks','ItemExt'])
print(df)
CustNum CustomerName ItemQty Item Seatblocks ItemExt
0 32363 McCartney, Paul 3 F04 2:218:10:4,6 60
1 31316 Lennon, John 25 F01 1:13:36:1,12 1:13:37:1,13 300
#first define a function: given a Series of string, split each element into a new series
def split_series(ser,sep):
return pd.Series(ser.str.cat(sep=sep).split(sep=sep))
#test the function,
split_series(pd.Series(['a b','c']),sep=' ')
0 a
1 b
2 c
dtype: object
df2=(df.groupby(df.columns.drop('Seatblocks').tolist()) #group by all but one column
['Seatblocks'] #select the column to be split
.apply(split_series,sep=' ') # split 'Seatblocks' in each group
.reset_index(drop=True,level=-1).reset_index()) #remove extra index created
print(df2)
CustNum CustomerName ItemQty Item ItemExt Seatblocks
0 31316 Lennon, John 25 F01 300 1:13:36:1,12
1 31316 Lennon, John 25 F01 300 1:13:37:1,13
2 32363 McCartney, Paul 3 F04 60 2:218:10:4,6
언급URL : https://stackoverflow.com/questions/17116814/how-to-split-text-in-a-column-into-multiple-rows
'programing' 카테고리의 다른 글
오류: com.google.gms를 찾을 수 없음: google-services: 4.2.0 (0) | 2023.06.18 |
---|---|
mmap()이 순차 IO보다 빠른 이유는 무엇입니까? (0) | 2023.06.18 |
VueJS - Store.dispatch에서 VueChart JS가 업데이트되지 않습니다. (0) | 2023.06.18 |
Firebase Auth를 사용할 때 앱이 충돌합니다. 이유: '기본 앱이 이미 구성되었습니다.' (0) | 2023.06.13 |
Routing resources for Rails에서 :id 매개변수의 이름 변경 (0) | 2023.06.13 |