Estou trabalhando com um arquivo csv grande e a penúltima coluna tem uma sequência de texto que eu quero dividir por um delimitador específico. Eu queria saber se existe uma maneira simples de fazer isso usando pandas ou python?
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
Quero dividir pelo espaço (' ')
e, em seguida, dois pontos (':')
na Seatblocks
coluna, mas cada célula resultaria em um número diferente de colunas. Eu tenho uma função para reorganizar as colunas para que a Seatblocks
coluna esteja no final da planilha, mas não tenho certeza do que fazer a partir daí. Posso fazê-lo no excel com a text-to-columns
função integrada e uma macro rápida, mas meu conjunto de dados possui muitos registros para o excel manipular.
Por fim, quero gravar registros como John Lennon e criar várias linhas, com as informações de cada conjunto de assentos em uma linha separada.
Respostas:
Isso divide os Seatblocks pelo espaço e dá a cada uma sua própria linha.
Ou, para fornecer cada sequência separada por dois pontos em sua própria coluna:
Isso é um pouco feio, mas talvez alguém entre em contato com uma solução mais bonita.
fonte
DataFrame
muito rapidamente. No meu caso, a execução do código em uma tabela ~ 200M resultou no uso de memória ~ 10G (+ swap ...).split()
, simplesmentereduce()
navegar pela coluna funciona como um encanto. O problema, então pode estar emstack()
...NameError: name 'Series' is not defined
para isso. de ondeSeries
deveria vir? EDIT: deixa pra lá, deve ser,pandas.Series
já que está se referindo ao item depandas
from pandas import Series
por conveniência / brevidade.Diferentemente de Dan, considero sua resposta bastante elegante ... mas, infelizmente, também é muito, muito ineficiente. Portanto, desde que a pergunta mencionou "um grande arquivo csv" , deixe-me sugerir tentar em um shell a solução de Dan:
... comparado a esta alternativa:
... e isto:
O segundo simplesmente evita alocar 100 000 Series, e isso é suficiente para torná-lo 10 vezes mais rápido. Mas a terceira solução, que ironicamente desperdiça muitas chamadas para str.split () (é chamada uma vez por coluna por linha, três vezes mais do que nas outras duas soluções), é cerca de 40 vezes mais rápida que a primeira, porque até evita instanciar as 100.000 listas. E sim, é certamente um pouco feio ...
EDIT: esta resposta sugere como usar "to_list ()" e para evitar a necessidade de um lambda. O resultado é algo como
que é ainda mais eficiente que a terceira solução e certamente muito mais elegante.
EDIT: o ainda mais simples
funciona também e é quase tão eficiente.
EDIT: ainda mais simples ! E lida com NaNs (mas menos eficiente):
fonte
tolist()
é perfeita. No meu caso eu só queria uma das peças de dados na lista e foi capaz de adicionar diretamente uma única coluna à minha df existente usando .ix:df['newCol'] = pd.DataFrame(df.col.str.split().tolist()).ix[:,2]
obect of type 'float' has no len()
que era desconcertante, até que percebi que algumas das minhas linhas estavamNaN
nelas, ao contráriostr
.Outra solução semelhante com encadeamento é o uso
reset_index
erename
:Se na coluna NÃO houver
NaN
valores, a solução mais rápida é usar alist
compreensão com oDataFrame
construtor:Mas se a coluna contém
NaN
apenas funcionastr.split
com o parâmetroexpand=True
que retornaDataFrame
( documentação ) e explica por que é mais lento:fonte
expand=True
opção de trabalharpandas.DataFrames
enquanto estiver usando,.str.split()
por exemplo.Outra abordagem seria assim:
fonte
Também pode usar groupby () sem a necessidade de se juntar e empilhar ().
Use os dados de exemplo acima:
fonte
0 31316 Lennon, John 25 F01 300 1:13:36:1,12 A
e a próxima linha0 31316 Lennon, John 25 F01 300 1:13:37:1,13 B
Esse parece um método muito mais fácil do que os sugeridos em outras partes deste segmento.
dividir linhas no dataframe do pandas
fonte