У меня есть DataFrame
с более чем 2 миллионами строк, который выглядит следующим образом:
+-------------------+--------------+--------+----------------------------+-------------+
| PartitionKey | RowKey | Type | Path | Name |
+-------------------+--------------+--------+----------------------------+-------------+
| / | /People | Folder | /People | People |
| /People | /index1.xlsx | File | /People/index1.xlsx | index1.xlsx |
| /People | /index2.xlsx | File | /People/index2.xlsx | index2.xlsx |
| /People | /index3.xlsx | File | /People/index3.xlsx | index3.xlsx |
| /People | /Employees | Folder | /People/Employees | Employees |
| /People/Employees | /cv1.pdf | File | /People/Employees/cv1.pdf | cv1.pdf |
| /People/Employees | /cv2.pdf | File | /People/Employees/cv2.pdf | cv2.pdf |
| /People/Employees | /cv3.pdf | File | /People/Employees/cv3.pdf | cv3.pdf |
| / | /Buildings | Folder | /Buildings | Buildings |
| /Buildings | /index1.xlsx | File | /Buildings/index1.xlsx | index1.xlsx |
| /Buildings | /index2.xlsx | File | /Buildings/index2.xlsx | index2.xlsx |
| /Buildings | /index3.xlsx | File | /Buildings/index3.xlsx | index3.xlsx |
| /Buildings | /Rooms | Folder | /Buildings/Rooms | Rooms |
| /Buildings/Rooms | /room1.pdf | File | /Buildings/Rooms/room1.pdf | room1.pdf |
| /Buildings/Rooms | /room2.pdf | File | /Buildings/Rooms/room2.pdf | room2.pdf |
| /Buildings/Rooms | /room3.pdf | File | /Buildings/Rooms/room3.pdf | room3.pdf |
+-------------------+--------------+--------+----------------------------+-------------+
Я хочу добавить два новых столбца: DirectFileCount
и RecursiveFileCount
.
Они должны указывать количество файлов в самой папке и количество файлов внутри себя и всех подпапок рекурсивно, в соответствии с отношением Path
-> PartitionKey
между папками и файлами.
Это должно сделать DataFrame
похожим на это:
+-------------------+--------------+--------+---------------------------+-------------+-----------------+--------------------+
| PartitionKey | RowKey | Type | Path | Name | DirectFileCount | RecursiveFileCount |
+-------------------+--------------+--------+---------------------------+-------------+-----------------+--------------------+
| / | /People | Folder | /People | People | 3 | 6 |
| /People | /index1.xlsx | File | /People/index1.xlsx | index1.xlsx | 0 | 0 |
| /People | /index2.xlsx | File | /People/index2.xlsx | index2.xlsx | 0 | 0 |
| /People | /index3.xlsx | File | /People/index3.xlsx | index3.xlsx | 0 | 0 |
| /People | /Employees | Folder | /People/Employees | Employees | 3 | 3 |
| /People/Employees | /cv1.pdf | File | /People/Employees/cv1.pdf | cv1.pdf | 0 | 0 |
| /People/Employees | /cv2.pdf | File | /People/Employees/cv2.pdf | cv2.pdf | 0 | 0 |
| /People/Employees | /cv3.pdf | File | /People/Employees/cv3.pdf | cv3.pdf | 0 | 0 |
+-------------------+--------------+--------+---------------------------+-------------+-----------------+--------------------+
У меня есть кое-что для прямого подсчета, которое работает:
df_count = df.groupby(['.tag', 'PartitionKey']).size().reset_index(name='counts')
df_file_count = df_count[df_count['.tag'] == 'file'].set_index('PartitionKey')
def direct_count(row):
if row['.tag'] == 'folder':
try:
return df_file_count.loc[row['path_lower']].counts
except:
pass
return 0
df['DirectFileCount'] = df.apply(lambda row: direct_count(row), axis=1)
Приведенный выше код заботится о DirectFileCount
изавершается менее чем за 2 минуты.
ОБНОВЛЕНИЕ 16 октября 2019
Я получил RecursiveFileCount
завершено, но это заняло 1 ч 52 мин. Код ниже:
dfc = df[df['Type'] == 'Folder'][['PartitionKey', 'DirectFileCount']].set_index('PartitionKey').groupby('PartitionKey').sum()
def recursive_count(row):
count = 0
if row['Type'] == 'Folder':
count = dfc[dfc.index.str.startswith(row['Path'])]['DirectFileCount'].sum()
return count
df['RecursiveFileCount'] = df.apply(lambda row: recursive_count(row), axis=1)
Теперь все работает, чтобы получить нужные мне результаты. Тем не менее, он довольно медленный с 2,7-метровыми строками, так что, надеюсь, у кого-то есть идеи по улучшению производительности.