Python: элегантный способ получить итерацию всех родителей в пути

In [28]: df = DataFrame(np.random.randn(1000000,10))

In [29]: df
Out[29]: 
<class 'pandas.core.frame.DataFrame'>
Int64Index: 1000000 entries, 0 to 999999
Data columns (total 10 columns):
0    1000000  non-null values
1    1000000  non-null values
2    1000000  non-null values
3    1000000  non-null values
4    1000000  non-null values
5    1000000  non-null values
6    1000000  non-null values
7    1000000  non-null values
8    1000000  non-null values
9    1000000  non-null values
dtypes: float64(10)

In [30]: frames = [ df.iloc[i*60:min((i+1)*60,len(df))] for i in xrange(int(len(df)/60.) + 1) ]

In [31]: %timeit [ df.iloc[i*60:min((i+1)*60,len(df))] for i in xrange(int(len(df)/60.) + 1) ]
1 loops, best of 3: 849 ms per loop

In [32]: len(frames)
Out[32]: 16667

Вот групповой способ (и вы можете сделать произвольное применение, а не сумму)

In [9]: g = df.groupby(lambda x: x/60)

In [8]: g.sum()    

Out[8]: 
<class 'pandas.core.frame.DataFrame'>
Int64Index: 16667 entries, 0 to 16666
Data columns (total 10 columns):
0    16667  non-null values
1    16667  non-null values
2    16667  non-null values
3    16667  non-null values
4    16667  non-null values
5    16667  non-null values
6    16667  non-null values
7    16667  non-null values
8    16667  non-null values
9    16667  non-null values
dtypes: float64(10)

Сумма cythonized, поэтому это так быстро

In [10]: %timeit g.sum()
10 loops, best of 3: 27.5 ms per loop

In [11]: %timeit df.groupby(lambda x: x/60)
1 loops, best of 3: 231 ms per loop
1
задан Bobby 17 January 2019 в 17:02
поделиться

3 ответа

Что-то вроде комбинации двух предыдущих ответов:

import pathlib
import os
def resources(path):
  parts = pathlib.Path(path).parts
  for n in range(len(parts), 1, -1):
    yield os.path.join(*parts[:n])
0
ответ дан Jeffrey Froman 17 January 2019 в 17:02
поделиться

Используйте pathlib . PurePath предлагают абстрактный интерфейс к объектам, подобным путям, которые не имеют отношения к файловой системе. В частности, PurePosixPath - это тот тип, который использует прямую косую черту (/) в качестве разделителей:

>>> from pathlib import PurePosixPath
>>> p = PurePosixPath('/house/dogs/ralph/bone')
>>> str(p.parent)
/house/dogs/ralph
>>> str(p.parent.parent)
/house/dogs

Вы можете сделать это легко:

p = PurePosixPath(...)
while p != p.root:
    # Do stuff to p
    p = p.parent
[1112 ] Достаточно питонным завершающим штрихом было бы сделать его генератором:

def receding_path(p):
    p = PurePosixPath(p)
    while p != p.root:
        yield str(p)
        p = p.parent

for item in receding_path('/house/dogs/ralph/bone'):
    # do stuff to each item
0
ответ дан Mad Physicist 17 January 2019 в 17:02
поделиться

Одним из способов было бы разбить строку на "/" и взять последовательные срезы.

in_string = "/house/dogs/ralph/bone"
s = in_string.split("/")
out_strings = list(filter(None, ("/".join(s[:i+1]) for i in range(len(s)))))
print(out_strings)
#['/house', '/house/dogs', '/house/dogs/ralph', '/house/dogs/ralph/bone']

filter(None, ...) используется для удаления пустых строк.

Или измените диапазон, если вы хотите выводить в порядке, указанном в вашем посте:

out_strings = list(filter(None, ("/".join(s[:i]) for i in range(len(s), 0, -1))))
print(out_strings)
#['/house/dogs/ralph/bone',
# '/house/dogs/ralph',
# '/house/dogs',
# '/house']
0
ответ дан pault 17 January 2019 в 17:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: